此篇文章介紹幾種主要位置函數及其之間的區別,以及各種與位置相關函數的使用場合;然后,通過一個簡單繪圖工具實例,介紹利用QPainter和QPainterPath兩種方法繪制各種基礎圖形;最后,通過幾個實例介紹如何利用這些基礎的圖形來繪制更復雜的圖形。
Qt位置相關函數
區別概念
Qt提供了很多關于獲取窗體位置及顯示區域大小的函數,如x()、y()和pos()、rect()、size()、geometry()等,統稱為“位置相關函數”或“位置函數”。幾種主要位置函數及其之間的區別如下所示。
其中,
- x()、y()和pos()函數的作用都是獲得整個窗體左上角的坐標位置。
- frameGeometry()函數與geometry ()函數相對應。frameGeometry()函數或獲得的是真個窗體的左頂點和長、寬值,而geometry ()函數獲得的是窗體內中央區域的左上頂點坐標及長、寬值。
- 直接調用width()和height()函數獲得的是中央區域的長、寬值。
- rect()、size()函數獲得的的結果也都是相對于窗體的中央區域而言的。size()函數獲得的是窗體得的長、寬值是相同的,都是窗體中央區域的長、寬值,rect()函數與geometry ()函數相同,返回一個QRect對象,,這兩個函數獲得的長、寬值是相同的,都是窗體中央區域的長、寬值,只是左上頂點的坐標值不一樣。geometry ()函數獲得的左上頂點坐標是相對于父窗體而言的坐標,而rect()函數獲得的左上頂點坐標始終為(0,0)。
在實際應用中,需要根據情況使用正確的位置信息函數以獲得準確的位置尺寸信息,尤其是在編寫對位置精度要求較高的程序(如地圖瀏覽程序)時,更應該注意函數的選擇,以避免產生不必要的誤差。
“實例”位置函數的應用
本節通過一個簡單的例子介紹QWidget提供的x()、y()、frameGeometry()、pos()、rect()、size()和geometry()等函數的使用場合。
創建一個Geometry項目,當改變對話框的大小或移動對話框時,調用各個函數所獲得的信息也相應地發生變化,從變化中可得知各函數之間的區別,效果如下圖所示。
布局代碼如下:
Geometry::Geometry(QWidget *parent): QDialog(parent)
{setWindowTitle(tr("Geometry"));xLabel =new QLabel(tr("x():"));xValueLabel =new QLabel;yLabel =new QLabel(tr("y():"));yValueLabel =new QLabel;FrmLabel =new QLabel(tr("Frame:"));FrmValueLabel =new QLabel;posLabel =new QLabel(tr("pos():"));posValueLabel =new QLabel;geoLabel =new QLabel(tr("geometry():"));geoValueLabel =new QLabel;widthLabel =new QLabel(tr("width():"));widthValueLabel =new QLabel;heightLabel =new QLabel(tr("height():"));heightValueLabel =new QLabel;rectLabel =new QLabel(tr("rect():"));rectValueLabel =new QLabel;sizeLabel =new QLabel(tr("size():"));sizeValueLabel =new QLabel;mainLayout =new QGridLayout(this);mainLayout->addWidget(xLabel,0,0);mainLayout->addWidget(xValueLabel,0,1);mainLayout->addWidget(yLabel,1,0);mainLayout->addWidget(yValueLabel,1,1);mainLayout->addWidget(posLabel,2,0);mainLayout->addWidget(posValueLabel,2,1);mainLayout->addWidget(FrmLabel,3,0);mainLayout->addWidget(FrmValueLabel,3,1);mainLayout->addWidget(geoLabel,4,0);mainLayout->addWidget(geoValueLabel,4,1);mainLayout->addWidget(widthLabel,5,0);mainLayout->addWidget(widthValueLabel,5,1);mainLayout->addWidget(heightLabel,6,0);mainLayout->addWidget(heightValueLabel,6,1);mainLayout->addWidget(rectLabel,7,0);mainLayout->addWidget(rectValueLabel,7,1);mainLayout->addWidget(sizeLabel,8,0);mainLayout->addWidget(sizeValueLabel,8,1);updateLabel();
}
頁面數據刷新updateLabel函數邏輯如下:
void Geometry::updateLabel()
{QString xStr; //獲得x()函數的結果并顯示xValueLabel->setText(xStr.setNum(x()));QString yStr; //獲得y()函數的結果并顯示yValueLabel->setText(yStr.setNum(y()));QString frameStr; //獲得frameGeometry()函數的結果并顯示QString tempStr1,tempStr2,tempStr3,tempStr4;frameStr = tempStr1.setNum(frameGeometry().x())+","+tempStr2.setNum(frameGeometry().y())+","+tempStr3.setNum(frameGeometry().width())+","+tempStr4.setNum(frameGeometry().height());FrmValueLabel->setText(frameStr);QString positionStr; //獲得pos()函數的結果并顯示QString tempStr11,tempStr12;positionStr =tempStr11.setNum(pos().x())+","+tempStr12.setNum(pos().y());posValueLabel->setText(positionStr);QString geoStr; //獲得geometry()函數的結果并顯示QString tempStr21,tempStr22,tempStr23,tempStr24;geoStr =tempStr21.setNum(geometry().x())+","+tempStr22.setNum(geometry().y())+","+tempStr23.setNum(geometry().width())+","+tempStr24.setNum(geometry().height());geoValueLabel->setText(geoStr);QString wStr,hStr; //獲得width()、height()函數的結果并顯示widthValueLabel->setText(wStr.setNum(width()));heightValueLabel->setText(hStr.setNum(height()));QString rectStr; //獲得rect()函數的結果并顯示QString tempStr31,tempStr32,tempStr33,tempStr34;rectStr =tempStr31.setNum(rect().x())+","+tempStr32.setNum(rect().y())+","+tempStr33.setNum(/*rect().width()*/width())+","+tempStr34.setNum(height()/*rect().height()*/);rectValueLabel->setText(rectStr);QString sizeStr; //獲得size()函數的結果并顯示QString tempStr41,tempStr42;sizeStr =tempStr41.setNum(size().width())+","+tempStr42.setNum(size().height());sizeValueLabel->setText(sizeStr);
}
重新定義QWidget的moveEvent(QMoveEvent *event)函數,響應對話框的移動事件,使得窗體在被動時能夠同步更新各函數的顯示結果,具體代碼如下:
void Geometry::moveEvent(QMoveEvent *)
{updateLabel();
}
重新定義QWidget的resizeEvent(QResizeEvent *event)函數,響應對話框的大小調整事件,使得在窗體大小發生變化時,也能夠同步更新各函數的顯示結果,具體代碼如下:
void Geometry::resizeEvent(QResizeEvent *)
{updateLabel();
}
Qt基礎圖形的繪制
創建一個PaintEx項目,在設計頁面區分各種形狀及畫筆顏色、畫筆線寬、畫筆風格、畫筆頂帽、畫筆連接點、填充模式、鋪展效果、畫刷顏色、畫刷風格設置等。
繪圖框架設計
利用QPainter繪制各種圖形使用的框架的實例如下圖所示。
此實例的具體實現包含兩個部分的內容:左側是用于畫圖的區域PaintArea類,右側是主窗口MainWidget類。
程序中,首先在PaintArea類中完成各種圖形顯示功能的Widget,重繪paintEvent函數。然后在主窗口MainWidget類中完成各種圖形參數的選擇。
繪圖區的實現
PaintArea類繼承自QWidget類,在類聲明中,首先聲明一個枚舉型數據Shape,列舉了所有本實例可能用到的圖形形狀;其次聲明setShape()函數用于設置形狀,setPen()函數用于設置畫筆,setBrush()函數用于設置畫刷,setFillRule()函數用于設置填充模式,以及重繪事件paintEvent()函數;最后聲明表示各種屬性的私有變量。
PaintArea類的構造函數用于完成初始化工作,設置圖形顯示區域的背景色及最小顯示尺寸,具體代碼如下:
PaintArea::PaintArea(QWidget *parent) : QWidget(parent)
{setPalette(QPalette(Qt::white));setAutoFillBackground(true);setMinimumSize(400,400);
}
其中,setPalette(QPalette(Qt::white))、setAutoFillBackground(true)完成對窗體背景色的設置,與下面的代碼效果一致:
QPalette p = palette();
p.setColor(QPalette::window, Qt::white);
setPalette(p);
setShape()函數可以設置形狀,setPen()函數可以涉資畫筆,setBrush()函數可以設置畫刷,setFillRule函數可以設置填充模式,具體代碼如下:
void PaintArea::setShape(Shape s)
{shape = s;update();
}
void PaintArea::setPen(QPen p)
{pen = p;update();
}
void PaintArea::setBrush(QBrush b)
{brush = b;update();
}
void PaintArea::setFillRule(Qt::FillRule rule)
{fillRule =rule;update(); //重畫繪制區窗體
}
PaintArea類的重繪函數代碼如下:
void PaintArea::paintEvent(QPaintEvent *)
{QPainter p(this); //新建一個QPainter對象p.setPen(pen); //設置QPainter對象的畫筆p.setBrush(brush); //設置QPainter對象的畫刷QRect rect(50,100,300,200);static const QPoint points[4]={QPoint(150,100),QPoint(300,150),QPoint(350,250),QPoint(100,300)};int startAngle = 30*16; int spanAngle = 120*16;QPainterPath path; //新建一個QPainterPath對象為畫路徑做準備path.addRect(150,150,100,100);path.moveTo(100,100);path.cubicTo(300,100,200,200,300,300);path.cubicTo(100,300,200,200,100,100);path.setFillRule(fillRule);switch(shape){case Line: //直線p.drawLine(rect.topLeft(),rect.bottomRight());break;case Rectangle: //長方形p.drawRect(rect); break;case RoundRect: //圓角方形p.drawRoundedRect(rect, 20.0, 20.0); break;case Ellipse: //橢圓形p.drawEllipse(rect); break;case Polygon: //多邊形p.drawPolygon(points,4); break;case Polyline: //多邊線p.drawPolyline(points,4); break;case Points: //點p.drawPoints(points,4); break;case Arc: //弧p.drawArc(rect,startAngle,spanAngle); break;case Path: //路徑p.drawPath(path); break;case Text: //文字p.drawText(rect,Qt::AlignCenter,tr("Hello Qt!"));break;case Pixmap: //圖片p.drawPixmap(150,150,QPixmap("butterfly.png")); break;default: break;}
}
- QRect rect(50,100,300,200):設定一個方形區域,為畫正方形、圓角正方形、橢圓等做準備。
- static const QPoint points[4]={…}:創建一個QPoint數組,包含4個點,為畫多邊形、多邊形及點做準備。
- int startAngle =3016:、int spanAngle = 12016:其中,startAngle 代表起始角,為弧形的起始點與圓心之間連線與水平方向的夾角;參數spanAngle表示的是跨度角,為弧形起點、終點分別于圓心連線之間的夾角
(用QPainter畫弧形所使用的角度值,是以1/16°為單位,在畫弧時即1°用16表示。)
。
主窗口的實現
界面布局代碼如下:
MainWidget::MainWidget(QWidget *parent): QWidget(parent)
{paintArea =new PaintArea;shapeLabel =new QLabel(QStringLiteral("形狀:")); //形狀選擇下拉列表框shapeComboBox =new QComboBox;shapeComboBox->addItem(QStringLiteral("Line"),PaintArea::Line);shapeComboBox->addItem(QStringLiteral("Rectangle"),PaintArea::Rectangle);shapeComboBox->addItem(QStringLiteral("RoundedRect"),PaintArea::RoundRect);shapeComboBox->addItem(QStringLiteral("Ellipse"),PaintArea::Ellipse);shapeComboBox->addItem(QStringLiteral("Polygon"),PaintArea::Polygon);shapeComboBox->addItem(QStringLiteral("Polyline"),PaintArea::Polyline);shapeComboBox->addItem(QStringLiteral("Points"),PaintArea::Points);shapeComboBox->addItem(QStringLiteral("Arc"),PaintArea::Arc);shapeComboBox->addItem(QStringLiteral("Path"),PaintArea::Path);shapeComboBox->addItem(QStringLiteral("Text"),PaintArea::Text);shapeComboBox->addItem(QStringLiteral("Pixmap"),PaintArea::Pixmap);connect(shapeComboBox,SIGNAL(activated(int)),this,SLOT(ShowShape (int)));penColorLabel =new QLabel(QStringLiteral("畫筆顏色:")); //畫筆顏色選擇控件penColorFrame =new QFrame;penColorFrame->setFrameStyle(QFrame::Panel|QFrame::Sunken);penColorFrame->setAutoFillBackground(true);penColorFrame->setPalette(QPalette(Qt::blue));penColorBtn =new QPushButton(QStringLiteral("更改"));connect(penColorBtn,SIGNAL(clicked()),this,SLOT(ShowPenColor()));penWidthLabel =new QLabel(QStringLiteral("畫筆線寬:")); //畫筆線寬選擇控件penWidthSpinBox =new QSpinBox;penWidthSpinBox->setRange(0,20);connect(penWidthSpinBox,SIGNAL(valueChanged(int)),this,SLOT (ShowPenWidth(int)));penStyleLabel =new QLabel(QStringLiteral("畫筆風格:")); //畫筆風格選擇下拉列表框penStyleComboBox =new QComboBox;penStyleComboBox->addItem(QStringLiteral("SolidLine"),static_cast<int>(Qt::SolidLine));penStyleComboBox->addItem(QStringLiteral("DashLine"),static_cast<int>(Qt::DashLine));penStyleComboBox->addItem(QStringLiteral("DotLine"),static_cast<int>(Qt::DotLine));penStyleComboBox->addItem(QStringLiteral("DashDotLine"),static_cast<int>(Qt::DashDotLine));penStyleComboBox->addItem(QStringLiteral("DashDotDotLine"),static_cast<int>(Qt::DashDotDotLine));penStyleComboBox->addItem(QStringLiteral("CustomDashLine"),static_cast<int>(Qt::CustomDashLine));connect(penStyleComboBox,SIGNAL(activated(int)),this,SLOT (ShowPenStyle(int)));penCapLabel =new QLabel(QStringLiteral("畫筆頂帽:")); //畫筆頂帽風格選擇下拉列表框penCapComboBox =new QComboBox;penCapComboBox->addItem(QStringLiteral("SquareCap"),Qt::SquareCap);penCapComboBox->addItem(QStringLiteral("FlatCap"),Qt::FlatCap);penCapComboBox->addItem(QStringLiteral("RoundCap"),Qt::RoundCap);connect(penCapComboBox,SIGNAL(activated(int)),this,SLOT (ShowPenCap (int)));penJoinLabel =new QLabel(QStringLiteral("畫筆連接點:"));//畫筆連接點風格選擇下拉列表框penJoinComboBox =new QComboBox;penJoinComboBox->addItem(QStringLiteral("BevelJoin"),Qt::BevelJoin);penJoinComboBox->addItem(QStringLiteral("MiterJoin"),Qt::MiterJoin);penJoinComboBox->addItem(QStringLiteral("RoundJoin"),Qt::RoundJoin);connect(penJoinComboBox,SIGNAL(activated(int)),this,SLOT (ShowPenJoin (int)));fillRuleLabel =new QLabel(QStringLiteral("填充模式:")); //填充模式選擇下拉列表框fillRuleComboBox =new QComboBox;fillRuleComboBox->addItem(QStringLiteral("Odd Even"),Qt::OddEvenFill);fillRuleComboBox->addItem(QStringLiteral("Winding"),Qt::WindingFill);connect(fillRuleComboBox,SIGNAL(activated(int)),this,SLOT (ShowFillRule()));spreadLabel =new QLabel(QStringLiteral("鋪展效果:")); //鋪展效果選擇下拉列表框spreadComboBox =new QComboBox;spreadComboBox->addItem(QStringLiteral("PadSpread"),QGradient::PadSpread); //(f)spreadComboBox->addItem(QStringLiteral("RepeatSpread"),QGradient:: RepeatSpread);spreadComboBox->addItem(QStringLiteral("ReflectSpread"),QGradient:: ReflectSpread);connect(spreadComboBox,SIGNAL(activated(int)),this,SLOT (ShowSpreadStyle()));brushColorLabel =new QLabel(QStringLiteral("畫刷顏色:")); //畫刷顏色選擇控件brushColorFrame =new QFrame;brushColorFrame->setFrameStyle(QFrame::Panel|QFrame::Sunken);brushColorFrame->setAutoFillBackground(true);brushColorFrame->setPalette(QPalette(Qt::green));brushColorBtn =new QPushButton(QStringLiteral("更改"));connect(brushColorBtn,SIGNAL(clicked()),this,SLOT (ShowBrushColor()));brushStyleLabel =new QLabel(QStringLiteral("畫刷風格:")); //畫刷風格選擇下拉列表框brushStyleComboBox =new QComboBox;brushStyleComboBox->addItem(QStringLiteral("SolidPattern"),static_cast<int>(Qt::SolidPattern));brushStyleComboBox->addItem(QStringLiteral("Dense1Pattern"),static_cast<int>(Qt::Dense1Pattern));brushStyleComboBox->addItem(QStringLiteral("Dense2Pattern"),static_cast<int>(Qt::Dense2Pattern));brushStyleComboBox->addItem(QStringLiteral("Dense3Pattern"),static_cast<int>(Qt::Dense3Pattern));brushStyleComboBox->addItem(QStringLiteral("Dense4Pattern"),static_cast<int>(Qt::Dense4Pattern));brushStyleComboBox->addItem(QStringLiteral("Dense5Pattern"),static_cast<int>(Qt::Dense5Pattern));brushStyleComboBox->addItem(QStringLiteral("Dense6Pattern"),static_cast<int>(Qt::Dense6Pattern));brushStyleComboBox->addItem(QStringLiteral("Dense7Pattern"),static_cast<int>(Qt::Dense7Pattern));brushStyleComboBox->addItem(QStringLiteral("HorPattern"),static_cast<int>(Qt::HorPattern));brushStyleComboBox->addItem(QStringLiteral("VerPattern"),static_cast<int>(Qt::VerPattern));brushStyleComboBox->addItem(QStringLiteral("CrossPattern"),static_cast<int>(Qt::CrossPattern));brushStyleComboBox->addItem(QStringLiteral("BDiagPattern"),static_cast<int>(Qt::BDiagPattern));brushStyleComboBox->addItem(QStringLiteral("FDiagPattern"),static_cast<int>(Qt::FDiagPattern));brushStyleComboBox->addItem(QStringLiteral("DiagCrossPattern"),static_cast<int>(Qt:: DiagCrossPattern));brushStyleComboBox->addItem(QStringLiteral("LinearGradientPattern"),static_cast<int>(Qt:: LinearGradientPattern));brushStyleComboBox->addItem(QStringLiteral("ConicalGradientPattern"),static_cast<int>(Qt:: ConicalGradientPattern));brushStyleComboBox->addItem(QStringLiteral("RadialGradientPattern"),static_cast<int>(Qt:: RadialGradientPattern));brushStyleComboBox->addItem(QStringLiteral("TexturePattern"),static_cast<int>(Qt::TexturePattern));connect(brushStyleComboBox,SIGNAL(activated(int)),this,SLOT (ShowBrush(int)));rightLayout =new QGridLayout; //控制面板的布局rightLayout->addWidget(shapeLabel,0,0);rightLayout->addWidget(shapeComboBox,0,1);rightLayout->addWidget(penColorLabel,1,0);rightLayout->addWidget(penColorFrame,1,1);rightLayout->addWidget(penColorBtn,1,2);rightLayout->addWidget(penWidthLabel,2,0);rightLayout->addWidget(penWidthSpinBox,2,1);rightLayout->addWidget(penStyleLabel,3,0);rightLayout->addWidget(penStyleComboBox,3,1);rightLayout->addWidget(penCapLabel,4,0);rightLayout->addWidget(penCapComboBox,4,1);rightLayout->addWidget(penJoinLabel,5,0);rightLayout->addWidget(penJoinComboBox,5,1);rightLayout->addWidget(fillRuleLabel,6,0);rightLayout->addWidget(fillRuleComboBox,6,1);rightLayout->addWidget(spreadLabel,7,0);rightLayout->addWidget(spreadComboBox,7,1);rightLayout->addWidget(brushColorLabel,8,0);rightLayout->addWidget(brushColorFrame,8,1);rightLayout->addWidget(brushColorBtn,8,2);rightLayout->addWidget(brushStyleLabel,9,0);rightLayout->addWidget(brushStyleComboBox,9,1);QHBoxLayout *mainLayout =new QHBoxLayout(this); //整體的布局mainLayout->addWidget(paintArea);mainLayout->addLayout(rightLayout);mainLayout->setStretchFactor(paintArea,1);mainLayout->setStretchFactor(rightLayout,0);ShowShape(shapeComboBox->currentIndex()); //顯示默認的圖形
}
- shapeComboBox->addItem(QStringLiteral(“Line”),PaintArea::Line):QComboBox的addItem函數可以僅插入文本,也可以同時插入文本相對應的具體數據,通常為枚舉類型數據,便于后面操作時確定選擇的是哪個數據。
- penStyleComboBox->addItem(QStringLiteral(“SolidLine”), static_cast(Qt::SolidLine)):選用不同的參數,對應畫筆的不同風格,如下圖所示。
- penCapComboBox->addItem(QStringLiteral(“SquareCap”),Qt::SquareCap):選用不同的參數,對應畫筆頂帽的不同風格,如下圖所示。
其中,Qt::SquareCap表示在線條的頂點處是方形的,且線條繪制的區域包括了端點,并且再往外延伸半個線寬長度;Qt::FlatCap表示在線條的頂點處是方形的,但線條繪制區域不包括端點在內;Qt::RoundCap表示在線條的頂點處是圓形,且線條繪制區域包含了端點。 - penJoinComboBox->addItem(QStringLiteral(“BevelJoin”),Qt::BevelJoin):選用不同的參數,對應畫筆連接點的不同風格,如下圖所示。
其中,Qt::BevelJoin風格連接點是指兩條線的中心線頂點相匯,相接處依然保留線條各自的方形頂端;Qt::MiterJoin風格連接點是指兩條線的中心頂點相匯,相連處線條延長到線的外側匯集至點,形成一個尖頂的連接;Qt::RoundJoin風格連接點是指兩條線的中心線頂點相匯,相連處圓弧形連接。 - fillRuleComboBox->addItem(QStringLiteral(“Odd Even”),Qt::OddEvenFill):Qt為QPainterPath類提供了兩種填充規則,分別是Qt::OddEvenFill和Qt::WindingFill,如下圖所示。這兩種填充規則在判定圖形中某一點處于內部還是外部時,判斷依據不同。
其中,Qt::OddEvenFill填充規則判斷的依據是從圖形中某一點畫一條水平線到圖形外。若這條水平線與圖形邊線的交點數目為奇數,則說明此點位于圖形的內部;若交點數目為偶數,則此點位于圖形的外部,如下圖所示。
而Qt::WindingFill填充規則的判斷依據則是從圖形中某一點畫一條水平線到圖形外,每個交點外邊線的方向可能向上,也可能向下,將這些交點數累加,方向相反的相互抵消,若最后結果不為0則說明此點在圖形內,若最后結果為0則說明在圖形外,如下圖所示。
其中,邊線方向是由QPainterPath創建時根據描述的順序決定的。如果采用addRect()或addPolygon()等函數加入圖形,默認是按順時針方向。 - spreadComboBox->addItem(QStringLiteral(“PadSpread”),QGradient::PadSpread):鋪展效果有三種,分別為QGradient::PadSpread、QGradient::RepeatSpread和QGradient::ReflectSpread。其中,PadSpread是默認的鋪展效果,也是最常見的鋪展效果,沒有被漸變覆蓋的區域填充單一的起始顏色或終止顏色;RepeatSpread效果與ReflectSpread效果只對線性漸變和圓形漸變起作用,如下圖所示。
使用QGradient的setColorAt()函數設置起止的顏色,其中,第一個參數表示所設顏色點的位置,取值范圍為0.0~1.0,0.0表示起點,1.0表示終點;第二個參數表示該點的顏色值。除可設置起點和終點的顏色外,如有需要還可以設置中間任意位置的顏色,例如,setColorAt(0.3,Qt::white),設置起、終點之間1/3位置的顏色為白色。 - brushStyleComboBox->addItem(QStringLiteral(“SolidPattern”), static_cast(Qt::SolidPattern)):選用不同的參數,對應畫刷的不同風格,如下圖所示。
ShowShape()槽函數,根據當前下拉列表框中選擇的選項,調用PaintArea類的setShape()函數設置PaintArea對象的形狀參數,具體代碼如下:
void MainWidget::ShowShape(int value)
{PaintArea::Shape shape = PaintArea::Shape(shapeComboBox->itemData(value,Qt::UserRole).toInt());paintArea->setShape(shape);
}
其中QComboBox類的itemData方法返回當前顯示的下拉列表框數據,是一個QVariant對象,此對象與控件初始化時插入枚舉型數據相關,調用QVariant類的toInt()函數獲得此數據在枚舉類型集合中的序號。
ShowPenColor()槽函數,利用標準顏色對話框QColorDialog獲取所選顏色,采用QFrame和QPushButton對象組合完成,QFrame對象負責顯示當前所選擇的顏色,QPushButton對象用于觸發標準顏色對話框進行顏色的選擇。
在此函數中獲得與畫筆相關的所有屬性值,包括畫筆顏色、畫筆線寬、畫筆風格、畫筆頂帽及畫筆連接點,共同構成QPen對象,并調用PaintArea對象的setPen()函數設置PaintArea對象的畫筆屬性。其他畫筆參數相關的響應函數完成的工作與此類似,具體代碼如下:
void MainWidget::ShowPenColor()
{QColor color = QColorDialog::getColor(static_cast<int>(Qt::blue));penColorFrame->setPalette(QPalette(color));int value = penWidthSpinBox->value();Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData(penStyleComboBox->currentIndex(),Qt::UserRole).toInt());Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData(penCapComboBox->currentIndex(),Qt::UserRole).toInt());Qt::PenJoinStyle join=Qt::PenJoinStyle(penJoinComboBox->itemData(penJoinComboBox->currentIndex(),Qt::UserRole).toInt());paintArea->setPen(QPen(color,value,style,cap,join));
}
ShowPenWidth()槽函數的具體實現代碼如下:
void MainWidget::ShowPenWidth(int value)
{QColor color = penColorFrame->palette().color(QPalette::Window);Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData(penStyleComboBox->currentIndex(),Qt::UserRole).toInt());Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData(penCapComboBox->currentIndex(),Qt::UserRole).toInt());Qt::PenJoinStyle join=Qt::PenJoinStyle(penJoinComboBox->itemData(penJoinComboBox->currentIndex(),Qt::UserRole).toInt());paintArea->setPen(QPen(color,value,style,cap,join));
}
ShowPenStyle()槽函數的具體實現代碼如下:
void MainWidget::ShowPenStyle(int styleValue)
{QColor color = penColorFrame->palette().color(QPalette::Window);int value = penWidthSpinBox->value();Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData(styleValue,Qt::UserRole).toInt());Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData(penCapComboBox->currentIndex(),Qt::UserRole).toInt());Qt::PenJoinStyle join=Qt::PenJoinStyle(penJoinComboBox->itemData(penJoinComboBox->currentIndex(),Qt::UserRole).toInt());paintArea->setPen(QPen(color,value,style,cap,join));
}
ShowPenCap()槽函數的具體實現代碼如下:
void MainWidget::ShowPenCap(int capValue)
{QColor color = penColorFrame->palette().color(QPalette::Window);int value = penWidthSpinBox->value();Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData(penStyleComboBox->currentIndex(),Qt::UserRole).toInt());Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData(capValue,Qt::UserRole).toInt());Qt::PenJoinStyle join=Qt::PenJoinStyle(penJoinComboBox->itemData(penJoinComboBox->currentIndex(),Qt::UserRole).toInt());paintArea->setPen(QPen(color,value,style,cap,join));
}
ShowPenJoin()槽函數的具體實現代碼如下:
void MainWidget::ShowPenJoin(int joinValue)
{QColor color = penColorFrame->palette().color(QPalette::Window);int value = penWidthSpinBox->value();Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData(penStyleComboBox->currentIndex(),Qt::UserRole).toInt());Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData(penCapComboBox->currentIndex(),Qt::UserRole).toInt());Qt::PenJoinStyle join=Qt::PenJoinStyle(penJoinComboBox->itemData(joinValue,Qt::UserRole).toInt());paintArea->setPen(QPen(color,value,style,cap,join));
}
ShowFillRule()槽函數的具體實現代碼如下:
void MainWidget::ShowFillRule()
{Qt::FillRule rule = Qt::FillRule(fillRuleComboBox->itemData(fillRuleComboBox->currentIndex(),Qt::UserRole).toInt());paintArea->setFillRule(rule);
}
ShowSpreadStyle()槽函數的具體實現代碼如下:
void MainWidget::ShowSpreadStyle()
{spread = QGradient::Spread(spreadComboBox->itemData(spreadComboBox->currentIndex(),Qt::UserRole).toInt());
}
ShowBrushColor()槽函數,與設置畫筆顏色函數類似,但選定顏色后并不直接調用PaintArea對象的setBrush()函數,而是嗲用ShowBrush()函數設置顯示區的畫刷屬性,具體實現代碼如下:
void MainWidget::ShowBrushColor()
{QColor color = QColorDialog::getColor(static_cast<int>(Qt:: blue));brushColorFrame->setPalette(QPalette(color));ShowBrush(brushStyleComboBox->currentIndex());
}
ShowBrush()槽函數具體實現代碼如下:
void MainWidget::ShowBrush(int value)
{//獲得畫刷的顏色QColor color = brushColorFrame->palette().color(QPalette:: Window);Qt::BrushStyle style = Qt::BrushStyle(brushStyleComboBox-> itemData(value,Qt::UserRole).toInt());if(style == Qt::LinearGradientPattern) {QLinearGradient linearGradient(0,0,400,400);linearGradient.setColorAt(0.0,Qt::white);linearGradient.setColorAt(0.2,color);linearGradient.setColorAt(1.0,Qt::black);linearGradient.setSpread(spread);paintArea->setBrush(linearGradient);}else if(style == Qt::RadialGradientPattern){QRadialGradient radialGradient(200,200,150,150,100);radialGradient.setColorAt(0.0,Qt::white);radialGradient.setColorAt(0.2,color);radialGradient.setColorAt(1.0,Qt::black);radialGradient.setSpread(spread);paintArea->setBrush(radialGradient);}else if(style == Qt::ConicalGradientPattern){QConicalGradient conicalGradient(200,200,30);conicalGradient.setColorAt(0.0,Qt::white);conicalGradient.setColorAt(0.2,color);conicalGradient.setColorAt(1.0,Qt::black);paintArea->setBrush(conicalGradient);}else if(style == Qt::TexturePattern){paintArea->setBrush(QBrush(QPixmap("butterfly.png")));}else{paintArea->setBrush(QBrush(color,style));}
}
- Qt::BrushStyle style = Qt::BrushStyle(brushStyleComboBox-> itemData(
value,Qt::UserRole).toInt()):獲得所選的畫刷風格,若選擇的是漸變或者紋理圖案,則需要進行一定處理。 - if(style == Qt::LinearGradientPattern):
主窗口的style變量值為Qt::LinearGradientPattern時,表明選擇的是圓形漸變。
QLinearGradient(const QPointF &start, const QPointF &finalStop)創建線性漸變類對象需要兩個參數,分別表示起止點位置。 - if(style == Qt::RadialGradientPattern):主窗口style變量值為Qt::RadialGradientPattern時,表明選擇的是圓形漸變。
QRadialGradient(const QPointF ¢er, qreal radius, const QPointF &focalPoint)創建圓形漸變類對象需要三個參數,分別表示圓心位置、半徑值和焦點位置。QRadialGradient(const QPointF ¢er, qreal radius, const QPointF &focalPoint)表示以center為作為圓心和焦點位置,以center和focalPoint之間的距離radius為半徑,當然圓心和焦點的位置也可以不重合。 - if(style == Qt::ConicalGradientPattern):主窗口的style變量值為Qt::ConicalGradientPattern時,表明選擇的是錐形漸變。
QConicalGradient(const QPointF ¢er, qreal angle)創建錐形漸變類對象需要兩個參數,分別是錐形的頂點位置和漸變分界線與水平方向的夾角,如下圖所示。錐形漸變不需要設置鋪展效果,它的鋪展效果只能是QGradient::PadSpread(注意:錐形漸變的方向默認是逆時針方向)
。
雙緩沖機制
原理與設計
所謂雙緩沖機制,是指在繪制控件時,首先將要繪制的內容繪制在一個圖片中,再將圖片一次性地繪制到控件上。在早期地Qt本版中,若直接在控件上進行繪制工作,則在控件重繪時會產生閃爍地現象,控件重繪頻繁時,閃爍尤為明顯。雙緩沖機制可以有效地消除這種閃爍現象。自Qt5版本之后,QWidget控件已經能夠自動處理閃爍地問題。因此,在控件上直接繪圖時,不用再操心顯示的閃爍問題,但雙緩沖機制在很多場合仍然尤其用武之地。當所需繪制的內容比較復雜并需要頻繁刷新,或者每次只需要刷新整個控件的一小部分時,仍應盡量采用雙緩沖機制。
創建一個DrawWidget項目實現一個簡單的繪圖工具,可以選擇線型、線寬、顏色等基本要素,如下圖所示。QMainWindows對象作為主窗口,QToolBar對象作為工具欄,QWidget對象作為主窗口的中央窗體,也就是繪圖區。
由于本實例是完成一個通過響應鼠標事件進行繪圖的功能,而這是在繪圖區窗體完成的,所以首先實現此窗體DrawWidget對鼠標事件進行重定義;然后實現可以選擇線型、線寬及顏色等基本要素的主窗口。
繪圖區的實現
DrawWidget類繼承自QWidget類,在類聲明中對鼠標事件mousePressEvent()和mouseMoveEvent()、重繪事件paintEvent()、尺寸變化事件resizeEvent()進行了重定義。setStyle()、setWidth()及setColor()函數主要用于為主窗口傳遞各種與繪圖有關的參數。
DrawWidget類布局代碼如下:
DrawWidget::DrawWidget(QWidget *parent) : QWidget(parent)
{setAutoFillBackground(true); //對窗體背景色的設置setPalette(QPalette(Qt::white));pix =new QPixmap(size()); //此QPixmap對象用來準備隨時接收繪制的內容pix->fill(Qt::white); //填充背景色為白色setMinimumSize(600,400); //設置繪制區窗體的最小尺寸
}
setStyle函數接收主窗口傳來的線型風格參數,setWidth函數接收主窗口傳來的線寬參數值,setColor函數接收主窗口傳來的畫筆顏色值。具體代碼如下:
void DrawWidget::setStyle(int s)
{style = s;
}
void DrawWidget::setWidth(int w)
{weight = w;
}
void DrawWidget::setColor(QColor c)
{color = c;
}
重定義鼠標按下事件mousePressEvent函數,在按下鼠標按鍵時,記錄當前的鼠標位置值startPos。
void DrawWidget::mousePressEvent(QMouseEvent *e)
{startPos = e->pos();
}
重定義鼠標事件mouseMoveEvent,鼠標移動事件在默認情況下,在刷表按鍵按下的同時拖拽鼠標時被觸發。
QWidget的mouseTracking屬性指示窗體是否追蹤鼠標,默認為false(不追蹤),即在至少有一個鼠標按鍵被按下的前提下移動鼠標才觸發mouseMoveEvent事件,可以通過setMouseTracking(bool enable)方法對該屬性值進行設置。如果設置的追蹤,則無論鼠標按鍵是否按下,只要鼠標移動,就會觸發mouseMoveEvent事件。在此事件處理函數中,完成QPixmap對象中繪圖的工作。具體代碼如下:
void DrawWidget::mouseMoveEvent(QMouseEvent *e)
{QPainter *painter = new QPainter; //新建一個QPainter對象QPen pen; //新建一個QPen對象pen.setStyle((Qt::PenStyle)style); pen.setWidth(weight); //設置畫筆的線寬值pen.setColor(color); //設置畫筆的顏色painter->begin(pix);painter->setPen(pen); //將QPen對象應用到繪制對象中//繪制從startPos到鼠標當前位置的直線painter->drawLine(startPos,e->pos());painter->end();startPos =e->pos(); //更新鼠標的當前位置,為下次繪制做準備update(); //重繪繪制區窗體
}
- pen.setStyle((Qt::PenStyle)style):設置畫筆的線型,style表示當前選擇的線型是Qt::PenStyle枚舉數據的第幾個元素。
- painter->begin(pix)、painter->end():以QPixmap對象為QPaintDevice參數繪制。在構造一個QPainter對象時,就立即開始對繪畫進行繪制。此構造QPainter對象是短時期的,如應定義在QWidget::paintEvent中,并只能調用一次。此構造函數調用開始于begin函數,并且在QPainter的析構函數中自動調用end函數。由于一個QPainter對象的初始化失敗時構造函數不能提供反饋信息,所以在繪制外部設備時應使用begin和end函數,如打印機等外部設備。
下面是使用begin和end函數的一個例子:
void DrawWidget::paintEvent(QPaintEvent *)
{QPainter painter;painter->begin(this);painter->drawLine(...);painter->end();
}
類似下面的形式:
void DrawWidget::paintEvent(QPaintEvent *)
{QPainter painter(this);painter.drawLine(...;
}
重繪函數paintEvent完成繪制區窗體的更新工作,只需要用drawPixmap函數將用于接收圖形繪制的QPixmao對象繪制再繪制區窗體控件上。具體代碼如下:
void DrawWidget::paintEvent(QPaintEvent *)
{QPainter painter(this);painter.drawPixmap(QPoint(0,0),*pix);
}
調整繪制區大小函數resizeEvent,當窗體的大小發生改變時,效果看起來像是繪制區大小改變了,但實際能夠進行繪制的區域仍然沒有改變。因為繪圖的大小并沒有改變,還是原來繪制區窗口的大小,所以在窗體尺寸變化是應及時調整用于繪制的QPixmap對象的大小。具體代碼如下:
void DrawWidget::resizeEvent(QResizeEvent *event)
{if(height()>pix->height()||width()>pix->width()){QPixmap *newPix = new QPixmap(size()); //創建一個新的QPixmap對象newPix->fill(Qt::white); //填充新QPixmap對象newPix的顏色為白色背景色QPainter p(newPix);p.drawPixmap(QPoint(0,0),*pix); //在newPix中繪制原pix中的內容pix = newPix; //將newPix賦值給pix作為新的繪制圖形接收對象}QWidget::resizeEvent(event); //完成其余的工作
}
- if(height()>pix->height()||width()>pix->width()):判斷改變后的窗體長或寬是否大于原窗體的長和寬。若大于則進行相應的調整,否則直接調用QWidget的resizeEvent函數返回。
clear函數完成繪制區的清楚工作,只需要調用一個新的、干凈的QPixmap對象來代替pix,并調用update函數重繪即可。具體代碼如下:
void DrawWidget::clear()
{QPixmap *clearPix =new QPixmap(size());clearPix->fill(Qt::white);pix = clearPix;update();
}
至此,一個能夠響應鼠標事件進行繪圖功能的窗體類DrawWidget已實現,可以進行接下來的工作,即在主窗口中應用此窗體類。
主窗口的實現
主窗口類MainWindow類繼承了QMainWindow類,只包含一個工具欄和一個中央窗體。首先,聲明一個構造函數、一個用于創建工具欄的函數createToolBar、一個用于進行選擇線型風格的槽函數ShowStyle和一個用于進行顏色選擇的槽函數ShowColor。然后,聲明一個DrawWidget類對象作為窗口的私有變量,以及聲明代表線型風格、線寬選擇、顏色選擇及清除按鈕的私有變量。
主界面構建代碼邏輯如下:
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{drawWidget =new DrawWidget; //新建一個DrawWidget對象setCentralWidget(drawWidget); //新建的DrawWidget對象作為主窗口的中央窗體createToolBar(); //實現一個工具欄setMinimumSize(600,400); //設置主窗口的最小尺寸ShowStyle(); //初始化線型,設置控件中的當前值作為初始值drawWidget->setWidth(widthSpinBox->value()); //初始化線寬drawWidget->setColor(Qt::black); //初始化顏色
}
createToolBar實現一個工具函數功能代碼如下:
void MainWindow::createToolBar()
{QToolBar *toolBar = addToolBar("Tool"); //為主窗口新建一個工具欄對象styleLabel =new QLabel(QStringLiteral("線型風格:")); //創建線型選擇控件styleComboBox =new QComboBox;styleComboBox->addItem(QStringLiteral("SolidLine"),static_cast<int>(Qt::SolidLine));styleComboBox->addItem(QStringLiteral("DashLine"),static_cast<int>(Qt::DashLine));styleComboBox->addItem(QStringLiteral("DotLine"),static_cast<int>(Qt::DotLine));styleComboBox->addItem(QStringLiteral("DashDotLine"),static_cast<int>(Qt::DashDotLine));styleComboBox->addItem(QStringLiteral("DashDotDotLine"),static_cast<int>(Qt::DashDotDotLine));//關聯相應的槽函數connect(styleComboBox,SIGNAL(activated(int)),this,SLOT(ShowStyle()));widthLabel =new QLabel(QStringLiteral("線寬:")); //創建線寬選擇控件widthSpinBox =new QSpinBox;connect(widthSpinBox,SIGNAL(valueChanged(int)),drawWidget,SLOT (setWidth(int)));colorBtn =new QToolButton; //創建顏色選擇控件QPixmap pixmap(20,20);pixmap.fill(Qt::black);colorBtn->setIcon(QIcon(pixmap));connect(colorBtn,SIGNAL(clicked()),this,SLOT(ShowColor()));clearBtn =new QToolButton(); //創建清除按鈕clearBtn->setText(QStringLiteral("清除"));connect(clearBtn,SIGNAL(clicked()),drawWidget,SLOT(clear()));toolBar->addWidget(styleLabel);toolBar->addWidget(styleComboBox);toolBar->addWidget(widthLabel);toolBar->addWidget(widthSpinBox);toolBar->addWidget(colorBtn);toolBar->addWidget(clearBtn);
}
改變線型參數的槽函數ShowStyle,通過調用DrawWidget類的setStyle函數將當前線型選擇控件中的線型參數傳給繪制區;設置畫筆顏色的槽函數ShowColor,通過調用DrawWidget類的setColor函數將用戶在標準顏色對話框中選擇的顏色值傳給繪制區。這兩個函數的具體代碼如下:
void MainWindow::ShowStyle()
{drawWidget->setStyle(styleComboBox->itemData(styleComboBox->currentIndex(),Qt::UserRole).toInt());
}void MainWindow::ShowColor()
{QColor color = QColorDialog::getColor(static_cast<int> (Qt::black), this);//使用標準顏色對話框QColorDialog獲得一個顏色值if(color.isValid()){//將新選擇的顏色傳給繪制區,用于改變畫筆的顏色值drawWidget->setColor(color);QPixmap p(20,20);p.fill(color);colorBtn->setIcon(QIcon(p)); //更新顏色選擇按鈕上的顏色顯示}
}
顯示Qt5 SVG格式圖片
SVG的英文全稱是Scalable Vector Graphics,即可縮放的矢量圖形。它是由萬維網聯盟在2000年8月制定的一種新的二維矢量圖形格式,也是規范中的網格矢量圖形標準,是一個開放的圖形標準。
SVG格式的特點如下:
- 基于XML。
- 采用文本來描述對象。
- 具有交互性和動態性。
- 完全支持DOM。
SVG相對于GIF、JPEG格式的優勢是,SVG是一種矢量圖形格式,比GIF、JPEG等柵格格式具有眾多優勢,如文件小,對于網絡而言,下載速度快;可任意縮放而不會破壞圖像的清晰度和細節;圖像中的文字獨立于圖像,文字保留可編輯和可搜尋的狀態,也沒有字體限制,用戶系統即使沒有安裝某一種字體,也可以看到與制作時完全相同的畫面等。正式基于其格式的各種優點及開放性,SVG得到了眾多組織和知名廠商的支持與認可,因此能夠迅速地開發和推廣應用。
Qt為SVG格式圖片地顯示與生成提供了專門的QtSvg模塊,此模塊中包含了與SVG圖片相關的所有類,主要有QSvgWidget、QSvgRender和QGraphicsSvgItem。
創建一個SVGTest項目,通過利用QSvgWidget類和QSvgRenderer類實現一個SVG圖片瀏覽器,顯示以".svg"結尾的文件以介紹SVG格式圖片顯示的方法,顯示效果如下圖所示。
注意,在此我們使用了顯示SVG的控件,需要在Makefile添加svg模塊的庫,如下圖所示。
打開svgwidget.cpp文件,在SvgWidget類構造函數獲得本窗體的QSvgRenderer對象,具體代碼如下:
SvgWidget::SvgWidget(QWidget *parent):QSvgWidget(parent)
{render =renderer();
}
以下是鼠標滾輪的響應事件,使SVG圖片能夠通過鼠標滾輪的滾動進行縮放。具體代碼如下:
void SvgWidget::wheelEvent(QWheelEvent *e)
{const double diff=0.1;QSize size =render->defaultSize();int width =size.width();int height =size.height();if(e->delta()>0){//對圖片的長、寬值進行處理,放大一定的比例width =int(this->width()+this->width()*diff);height =int(this->height()+this->height()*diff);}else{//對圖片的長、寬值進行處理,縮小一定的比例width =int(this->width()-this->width()*diff);height =int(this->height()-this->height()*diff);}resize(width,height); //利用新的長、寬值對圖片進行resize()操作
}
- const double diff=0.1:diff的值表示每次滾動一定的值,圖片大小改變的比例。
- QSize size =render->defaultSize():該行代碼及下面兩行代碼用于獲取圖片顯示區的尺寸,以便進行下一步的縮放操作。
- if(e->delta()>0):利用QWheelEvent的delta函數獲得滾動的距離值,通過此值來判斷滾輪滾動的方向。若delta值大于0,則表示滾輪向前(遠離用戶的方向)滾動;若小于0則表示向后(靠近用戶的方向)滾動。
鼠標滾動事件,滾輪每滾動1°相當于移動了8°,而常見的滾輪鼠標撥動以下滾動的角度為15°,因此滾輪波動一下相當于移動了120(=15*8)。
SvgWindow類繼承自QScrollArea類,是一個帶滾動條的顯示區域。在SvgWindow類實現中包含SvgWidget類的頭文件。SvgWindow類使圖片在放大到超過主窗口大小時,能夠通過拖拽滾動條的方式進行查看。
SvgWindow類的構造函數,構造SvgWidget對象,并調用QScrollArea類的setWidget函數設置滾動區的窗體,使svgWidget成為SvgWindow的子窗口。具體代碼如下。
SvgWindow::SvgWindow(QWidget *parent):QScrollArea(parent)
{svgWidget =new SvgWidget;setWidget(svgWidget);
}
當主窗口中對文件進行了選擇或修改時,將調用setFile函數設置新的文件,具體代碼如下:
void SvgWindow::setFile(QString fileName)
{svgWidget->load(fileName);QSvgRenderer *render =svgWidget->renderer();svgWidget->resize(render->defaultSize());
}
- svgWidget->load(fileName):將新的SVG文件加載到svgWidget中進行顯示。
- svgWidget->resize(render->defaultSize()):使svgWidget窗體按SVG圖片的默認尺寸進行顯示。
當鼠標被按下時,對mousePressPos和scrollBarValuesOnMousePress進行初始化,QScrollArea類的horizontalScrollBar和verticalScrollBar函數可以分別獲得svgWidget的水平滾動條和垂直滾動條。具體代碼如下:
void SvgWindow::mousePressEvent(QMouseEvent *event)
{mousePressPos =event->pos();scrollBarValuesOnMousePress.rx()=horizontalScrollBar()->value();scrollBarValuesOnMousePress.ry()=verticalScrollBar()->value();event->accept();
}
當鼠標被按下并拖拽鼠標時觸發mouseMoveEvent函數,通過滾動條的位置設置實現圖片的拖拽效果,具體代碼如下:
void SvgWindow::mouseMoveEvent(QMouseEvent *event)
{//對水平滑動條的新位置進行設置horizontalScrollBar()->setValue(scrollBarValuesOnMousePress.x()-event->pos().x()+mousePressPos.x());//對垂直滑動條的新位置進行設置verticalScrollBar()->setValue(scrollBarValuesOnMousePress.y()-event->pos().y()+mousePressPos.y());horizontalScrollBar()->update();verticalScrollBar()->update();event->accept();
}
主窗口MainWindow繼承QMainWindow類,包含一個菜單欄,其中有一個“文件”菜單條,包含一個“打開”菜單項。
MainWindow構造函數中,創建一個SvgWindow對象作為主窗口的中央窗體。具體代碼如下:
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{setWindowTitle(QStringLiteral("SVG Viewer"));createMenu();svgWindow =new SvgWindow;setCentralWidget(svgWindow);setMinimumSize(400, 300);
}
創建菜單欄具體代碼如下:
void MainWindow::createMenu()
{QMenu *fileMenu = menuBar()->addMenu(QStringLiteral("文件"));QAction *openAct = new QAction(QStringLiteral("打開"),this);connect(openAct,SIGNAL(triggered()),this,SLOT(slotOpenFile()));fileMenu->addAction(openAct);
}
通過標準文件對話框選擇SVG文件,并調用SvgWindow窗口的setFile函數將選擇的文件名傳遞給svgWindow進行顯示,具體代碼如下:
void MainWindow::slotOpenFile()
{QString name =QFileDialog::getOpenFileName(this, QStringLiteral("打開"),"./","svg files(*.svg)");svgWindow->setFile(name);
}
工程源碼
文章設計所有代碼可點擊工程源碼下載查看。