Qt中建菜单栏和工具栏(泊松编辑)

来源:互联网 发布:淘宝如何拆分订单发货 编辑:程序博客网 时间:2024/06/09 20:00

最近在学Qt,以下为学习过程(在VS中运用Qt):

建菜单栏时可以直接在Qt Designer里建,但是之后在建立菜单栏信号和槽连接的时候我不知道怎么弄了,百度了下说是在Designer里面只能使用里面自带的槽。所以我最后用直接写代码的方式建立了菜单栏和工具栏,代码如下:

#include "mainwindow.h"#include <QAction>MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags): QMainWindow(parent, flags){ui.setupUi(this);openAction = new QAction(tr("&Open"), this); openAction->setShortcut(QKeySequence::Open); QMenu *file = menuBar()->addMenu(tr("&File")); file->addAction(openAction); QToolBar *toolBar = addToolBar(tr("&File")); toolBar->addAction(openAction);connect(openAction, SIGNAL(triggered()), this, SLOT(openImage()));}


之后我想读取图片并显示出来,刚开始只能显示一张,如果再打开一张,前面一张会消失,后来又加了一个读取图片的并改变了图片显示的位置,从而可以连续的打开两张图片。(此处有待学习,待之后学会了再改进),代码如下:

void MainWindow::openImage(){QString filename=QFileDialog::getOpenFileName(this, tr("Open Image"),"", tr("BMP(*.bmp);;JPG(*.jpg);;ALL files(*.*)")); if(filename.isEmpty()) { QMessageBox::information(this,tr("Open Image"), tr("Please select an image to open")); filename=QFileDialog::getOpenFileName(this, tr("Open Image"),"", tr("BMP(*.bmp);;JPG(*.jpg);;ALL files(*.*)")); } if(!(img1.load(filename,0))) { QMessageBox::information(this,tr("Unable to open the Image"), tr("Please select a valid image.")); return; } QWidget::update(); QString filename2=QFileDialog::getOpenFileName(this, tr("Open Image"),"", tr("BMP(*.bmp);;JPG(*.jpg);;ALL files(*.*)")); if(filename2.isEmpty()) { QMessageBox::information(this,tr("Open Image"), tr("Please select an image to open")); filename=QFileDialog::getOpenFileName(this, tr("Open Image"),"", tr("BMP(*.bmp);;JPG(*.jpg);;ALL files(*.*)")); } if(!(img2.load(filename2,0))) { QMessageBox::information(this,tr("Unable to open the Image"), tr("Please select a valid image.")); return; } QWidget::update(); }

我们使用了setShortcut函数。shortcut是这个动作的快捷键。Qt的QKeySequence已经为我们定义了很多内置的快捷键,比如我们使用的Open。你可以通过查阅API文档获得所有的快捷键列表,或者是在QtCreator中输入::后会有系统的自动补全功能显示出来。这个与我们自己定义的有什么区别呢?简单来说,我们完全可以自己定义一个tr("Ctrl+O")来实现快捷键。原因在于,这是Qt跨平台性的体现。比如PC键盘和Mac键盘是不一样的,一些键在PC键盘上有,而Max键盘上可能并不存在,或者反之,所以,推荐使用QKeySequence类来添加快捷键,这样,它会根据平台的不同来定义不同的快捷键。

QMainWindow有一个menuBar()函数,会返回菜单栏,也就是最上面的那一条。如果不存在会自动创建,如果已经存在就返回那个菜单栏的指针。直接使用返回值添加一个菜单,也就是addMenu,参数是一个QString,也就是显示的菜单名字。然后使用这个QMenu指针添加这个QAction。类似的,使用addToolBar函数的返回值添加了一个工具条,并且把这个QAction添加到了上面。

void MainWindow::paintEvent(QPaintEvent *event) { QPainter painter(this); if(!img1.isNull()) painter.drawImage(50,50,img1); if(!img2.isNull()) painter.drawImage(50,250,img2); } 


接下来又用双缓冲绘图的方法在窗口中画矩形(选取图片上的某个区域),该方法可以使用鼠标在界面上绘制一个任意大小的矩形。这里需要两张画布,其中一个tempPix用来作为临时缓冲区,当鼠标正在拖动矩形进行绘制时,将内容先绘制到tempPix上,然后将tempPix绘制到界面上;而另一个pix作为缓冲区,用来保存已经完成的绘制。当松开鼠标完成矩形的绘制后,则将tempPix的内容复制到pix上,为了绘制时不显示拖影,那么在移动鼠标的过程中,每绘制一次,都要在刚开始绘制这个矩形的图像上进行绘制,所以需要在每次绘制tempPix之前,先将pix的内容复制到tempPix上。代码如下:


void MainWindow::paintEvent(QPaintEvent *event) { QPainter painter(this); if(!img1.isNull()) painter.drawPixmap(50,50,img1); if(!img2.isNull()) painter.drawPixmap(400,50,img2);tempPix=pix;isDrawing=false;int x=startPoint.x();int y=startPoint.y();int width=endPoint.x()-x;int height=endPoint.y()-y;painter.begin(&tempPix);QPen pen(Qt::blue,2,Qt::DotLine);painter.setPen(pen);painter.drawRect(x,y,width,height);painter.end();painter.begin(this);painter.drawPixmap(0,0,tempPix);if (!isDrawing)pix=tempPix;} 
void MainWindow::mousePressEvent(QMouseEvent *event){if (event->button()==Qt::LeftButton){startPoint=event->pos();isDrawing=true;}}void MainWindow::mouseMoveEvent(QMouseEvent *event){if (event->buttons() & Qt::LeftButton){endPoint=event->pos();tempPix=pix;update();}}void MainWindow::mouseReleaseEvent(QMouseEvent *event){if (event->button()==Qt::LeftButton){endPoint=event->pos();isDrawing=false;update();}}

虽然可以画出矩形,但是最好是限定在所显示的图像区域内,后期再改进。

以上我其实是先读取两张图片,然后在其中一张图片上用矩形框选取一部分图像,然后把这部分图像粘贴到另一张另图片,目的达到无缝融合。

我先试着把所选取的这部分图片直接复制粘贴到另一张图像上,然后再试着用泊松融合来处理。直接复制粘贴的这部分代码如下:

void MainWindow::paintEvent(QPaintEvent *event) { if (flag==false){QPainter painter(this);   if(!img1.isNull())   painter.drawImage(0,50,img1);   if(!img2.isNull())   painter.drawImage(400,50,img2);  tempPix=pix;  isDrawing=false;  int x=startPoint.x();  int y=startPoint.y();   width=endPoint.x()-x;   height=endPoint.y()-y;  painter.begin(&tempPix);  QPen pen(Qt::red,2,Qt::DotLine);  painter.setPen(pen);  painter.drawRect(x,y,width,height);  painter.end();  painter.begin(this);  painter.drawImage(0,0,tempPix);  if (!isDrawing)  pix=tempPix; Boundarypoint[0]=x;Boundarypoint[1]=y;Boundarypoint[2]=width;Boundarypoint[3]=height;}else if (flag==true){QPainter painter(this); painter.begin(this);QRect rect1 = QRect(0, 50, img1.width(), img1.height());painter.drawImage(rect1, img1);QRect rect2 = QRect(400,50, img2.width(), img2.height());painter.drawImage(rect2, img2);painter.end();painter.begin(this);int newx=startPoint.x();int newy=startPoint.y();int k=0;for (int i=newx-400;i<newx-400+width;i++){int m=0;for (int j=newy-50;j<newy+height-50;j++){QRgb value;value=img1.pixel(Boundarypoint[0]+k,Boundarypoint[1]-50+m);m++;img2.setPixel(i,j,value);}k++;}QRect rect = QRect(400, 50, img2.width(), img2.height());painter.drawImage(rect, img2);painter.end();}} void MainWindow::copyImage(){flag=true;}

做了好几天终于把泊松融合用Qt做出来了,简单描述一下:

这里要感谢博主http://blog.csdn.net/hjimce/article/details/45716603,看完这个就会对泊松编辑有更好的理解

按步骤首先是要先求所选区域的梯场,再求背景图片的梯度场,然后求融合图像的梯度场,最后求融合图像的散度(对梯度求导),这些要求解系数矩阵。我用的是MKL来求解泊松方程。

我做的时候就直接求了所选区域内部点的散度,粘贴到背景图中。而原图中所选的区域的边界点是不求的,而用的是边界点在背景图的位置处来求解,把背景图放在边界点方程的右边,前面求的内部点的散度也放在右边,根据那个链接里的拉普拉斯算子来求。方程左边就是该点相邻的内部点取1,和该点取-4,最后求解。因为我是直接求的散度,所以还是有所偏差。

说的不清楚,就是记录一下怕自己忘了。有很多不足的地方待改进。

部分代码如下:(方法比较笨)

void MainWindow::PossionEquation(numc::RowMat<double>& rmt, vector<double>& rhsR, vector<double>& rhsG,vector<double>& rhsB){int divR,divG,divB;k=0;    //标号0,1......for (int y1=Boundarypoint[1]-50+1;y1<Boundarypoint[1]-50+height-1;y1++)    //求矩形区内部点的散度{for (int x1=Boundarypoint[0]+1;x1<Boundarypoint[0]+width-1;x1++){QColor color(img1.pixel(x1,y1));QColor color1(img1.pixel(x1+1,y1));QColor color2(img1.pixel(x1-1,y1));QColor color3(img1.pixel(x1,y1+1));QColor color4(img1.pixel(x1,y1-1));divR=color1.red()+color2.red()+color3.red()+color4.red()-4*color.red();rhsB[k]=divR;divG=color1.green()+color2.green()+color3.green()+color4.green()-4*color.green();rhsG[k]=divG;divB=color1.blue()+color2.blue()+color3.blue()+color4.blue()-4*color.blue();rhsB[k]=divB;k++;}}for(int i=0;i<n;i++){if (i==0){rmt[0][1]=1;rmt[0][width-2]=1;QColor Co1(img2.pixel(newx-399,newy-50));QColor Co2(img2.pixel(newx-400,newy-49));rhsR[i]=rhsB[i]-Co1.red()-Co2.red();rhsG[i]=rhsG[i]-Co1.green()-Co2.green();rhsB[i]=rhsB[i]-Co1.blue()-Co2.blue();}else if(i==width-3){rmt[i][width-4]=1;rmt[i][2*width-5]=1;QColor Co1(img2.pixel(newx+width-402,newy-50));QColor Co2(img2.pixel(newx+width-401,newy-49));rhsR[i]=rhsB[i]-Co1.red()-Co2.red();rhsG[i]=rhsG[i]-Co1.green()-Co2.green();rhsB[i]=rhsB[i]-Co1.blue()-Co2.blue();}else if (i==n-width+2){rmt[i][n-2*width+4]=1;rmt[i][n-width+3]=1;QColor Co1(img2.pixel(newx-399,newy+height-51));QColor Co2(img2.pixel(newx-400,newy+height-52));rhsR[i]=rhsB[i]-Co1.red()-Co2.red();rhsG[i]=rhsG[i]-Co1.green()-Co2.green();rhsB[i]=rhsB[i]-Co1.blue()-Co2.blue();}else if (i==n-1){rmt[i][n-width+1]=1;rmt[i][n-2]=1;QColor Co1(img2.pixel(newx+width-401,newy+height-52));QColor Co2(img2.pixel(newx+width-402,newy+height-51));rhsR[i]=rhsB[i]-Co1.red()-Co2.red();rhsG[i]=rhsG[i]-Co1.green()-Co2.green();rhsB[i]=rhsB[i]-Co1.blue()-Co2.blue();}else if (i>0&&i<width-3){rmt[i][i-1]=1;rmt[i][i+1]=1;rmt[i][i+width-2]=1;QColor Co(img2.pixel(newx+i-399,newy-50));rhsR[i]=rhsB[i]-Co.red();rhsG[i]=rhsG[i]-Co.green();rhsB[i]=rhsB[i]-Co.blue();}else if (i%(width-2)==0){rmt[i][i-width+2]=1;rmt[i][i+1]=1;rmt[i][i+width-2]=1;QColor Co(img2.pixel(newx-400,newy-49+i/(width-2)));  ////rhsR[i]=rhsB[i]-Co.red();rhsG[i]=rhsG[i]-Co.green();rhsB[i]=rhsB[i]-Co.blue();}else if (i>(n-width+2)&&i<n-1){rmt[i][i-1]=1;rmt[i][i+1]=1;rmt[i][i-width+2]=1;QColor Co(img2.pixel(newx-399+i-(n-width+2),newy+height-51));rhsR[i]=rhsB[i]-Co.red();rhsG[i]=rhsG[i]-Co.green();rhsB[i]=rhsB[i]-Co.blue();}else if (i%(width-2)==(width-3)){rmt[i][i-width+2]=1;rmt[i][i-1]=1;rmt[i][i+width-2]=1;QColor Co(img2.pixel(newx+width-401,newy-49+i/(width-3)));////rhsR[i]=rhsB[i]-Co.red();rhsG[i]=rhsG[i]-Co.green();rhsB[i]=rhsB[i]-Co.blue();}else{rmt[i][i-width+2]=1;rmt[i][i-1]=1;rmt[i][i+1]=1;rmt[i][i+width-2]=1;}rmt[i][i]=-4;}}void MainWindow::PossionSolver(){using namespace numc;RowMat<double> rmt(n, n);//根据内部点像素建立方程vector<double> rhsR(n);//R通道右边值vector<double> rhsG(n);//G通道右边值vector<double> rhsB(n);//B通道右边值PossionEquation(rmt,rhsR,rhsG,rhsB);#if TESTstd::ofstream outfile1;outfile1.open("equation.txt");for (int i =0; i < n; i ++){outfile1 << "Row" << i << std::endl;for (int j = 0; j < n; j ++){outfile1 << rmt[i][j] << " "; }outfile1 << "\t" << rhsU[i] << " " << rhsV[i] << std::endl;}outfile1.close();#endifCSRMatrix<double> m;CreateCSRMatrixFromRowMap(m,rmt);numc::CLeastSquareSpareSolver solver;solver.init(m);vector<double> resultR(n);vector<double> resultG(n);vector<double> resultB(n);solver.solve(&rhsR.front(), &resultR.front());solver.solve(&rhsG.front(), &resultG.front());solver.solve(&rhsB.front(), &resultB.front());#if TESTfor (int i = 0; i < n ; i++){std::cout<<resultU[i]<<" " << resultV[i] << std::endl;}#endiffor (int q=0;q<n;q++){if (resultR[q]>255)resultR[q]=255;if (resultR[q]<0)resultR[q]=0;if (resultG[q]>255)resultG[q]=255;if (resultG[q]<0)resultG[q]=0;if (resultB[q]>255)resultB[q]=255;if (resultB[q]<0)resultB[q]=0;}int p=0;for (int j=newy-50+1;j<newy-50+height-1;j++){for (int i=newx-400+1;i<newx-400+width-1;i++){QRgb value=qRgba(resultR[p],resultG[p],resultB[p],255);img2.setPixel(i,j,value);p++;}}}
这里因为图片显示的位置和窗口的位置存在一个相对位置,所以要-400,-50
结果如下:




注:初学,还有很多不懂不明白的地方,还望有大神可以指导改进一下。

0 0
原创粉丝点击