C++GUI Qt 4 编程-第八章 基于项的图形视图

    xiaoxiao2026-06-07  3

    //修改1——20170626

    经过几周的奋斗,每天几个小时的研究,总算大致把书上的历程自己给实现了一遍,很多相似功能知识做了个例子,并没有做的全面,原因是一方面由于,时间的限制,18号就去上班了,但本职工作并不是和软件相关,软件只是个兴趣,以后没有这么多时间去研究,另一方面很多功能相似,操作都类似,就没有必要再去实施一遍了,这样比较省时间吧。下面是自己的研究的大致过程,简单的东西就没再写了:

    1、搞懂QGraphicsItem中:boundingRect()和paint()成员函数的使用方式

    boundingRect()其实就是决定了整个Item的最大的边界,当Item中的内容大于边界的容量时,能容只会部分显示。

    void QGraphicsItem::paint()是在程序一开始就会直接调用,完成初始化的操作,不需要信号和槽的支持,可以理解为自动事件吧。。。。。

    paint()为虚函数。

    在本程序中的subclass中使用如下:

    void NewItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget ) { QPen pen(Qt::darkBlue); if(option->state&QStyle::State_Selected)//画的时候,State_Selected——Used to indicate if a widget is selected. { //被选择时 pen.setStyle(Qt::DotLine); pen.setWidth(2); } painter->setPen(pen); painter->setBrush(Qt::white); QRectF rect(x,y,45,30); painter->drawRoundedRect(rect,rect.width()/2.0,rect.height()/2.0); painter->setPen(Qt::darkGreen); painter->drawText(rect,Qt::AlignCenter,text); }

    2、设置Item的几何位置。

    方法一、通过paint()中的代码:

    QRectF rect(x,y,45,30); painter->drawRoundedRect(rect,rect.width()/2.0,rect.height()/2.0);

    方法二、可以重载子类构造函数,用参数决定Item的位置:

    NewItem::NewItem(qreal a,qreal b) { setFlags(ItemIsMovable|ItemIsSelectable); x=a; y=b; text="text1"; }

    3、另附好用的InputDialog:

    QInputDialog inputdialog; bool OK; QString tmptext; QString gettext=inputdialog.getText(event->widget(),"Edit Text","Enter new text:",QLineEdit::Normal,tmptext,&OK); if(OK&&!text.isEmpty())//QInputDialog 好用!!!!!!!!!!!!!!! { text=gettext; prepareGeometryChange();//大小、形状改变时调用 }

    4、通过选项改变Item里面的数据

    联系上文:当使用update()和prepareGeometryChange()是要调用:paint();故在paint()函数中设置传递变量就可以了:

    painter->drawText(rect,Qt::AlignCenter,text);

    5、菜单类

    a)先设置动作,再创建菜单

    b)菜单栏和工具栏的位置怎么弄???

    1.菜单栏创建 

    直接使用 QMainWindow::menuBar()函数即可返回一个QMenuBar指针;

    2.工具栏 

    定义了QToolBar *toolbar之后,不用new分配空间,直接用toolbar=addToolBar(" &New") newaction->setIcon(QIcon("00.jpg"));   插入图片时别改图片的格式

    6、图形化菜单

    setIconSize(QSize())设置图标的大小。。

    7、连线两个NewItem(画条直线)

    QGraphicsItem::pos()返回的是Item的左上坐标。 具体的实现函数:

    void lineItem::trackNodes() { QPoint f1(one->pos().x()+15,one->pos().y()+20); QPoint f2(two->pos().x()+15,two->pos().y()+20); setLine(QLineF(f1,f2)); }

    8、数据存取

    a)存 NewItem的 位置大小和文本以及lineItem的位置 即可

    b)再读取,就可以恢复原状态

    bool DiagramWindow::read() { QFile file("Graphics"); if(!file.open(QIODevice::ReadOnly)){ QMessageBox::warning(this,tr("QGraphhics"),tr("Cannot read file %1:\n%2.") .arg(file.fileName()).arg(file.errorString())); return false; } QDataStream in(&file); in.setVersion(QDataStream::Qt_5_2); quint32 magic; in>>magic; if(magic!=MagicNumber){ QMessageBox::warning(this,tr("QGraphics"),tr("The file is not a Spreadsheet file")); return false; } qreal x; qreal y; while(!in.atEnd()) { in>>x>>y; NewItem *newitem=new NewItem(x,y); newitem->setSelected(true); scene->addItem(newitem); view->setScene(scene); update(); } QApplication::restoreOverrideCursor(); return true; } bool DiagramWindow::save() { QFile file("Graphics"); if(!file.open(QIODevice::WriteOnly)){ QMessageBox::warning(this,"Graphics",tr("Cannot write file %1:\n%2.").arg(file.fileName()) .arg(file.errorString())); return false; } QDataStream out(&file); out.setVersion(QDataStream::Qt_5_2); out<<quint32(MagicNumber); QApplication::setOverrideCursor(Qt::WaitCursor); QList<QGraphicsItem*>items=scene->items(); QMutableListIterator<QGraphicsItem*>i(items); QGraphicsItem*tmp; while(i.hasNext()) { tmp=i.next(); out<<qreal(tmp->pos().x())<<qreal(tmp->pos().y()); } QApplication::restoreOverrideCursor(); return true; } (注:不能直接把QGraphicsItem或者其subclass作为基本类型传递,但可以把相关数据,如位置,文本,等通过变量存取。)

    新注:都可以传递,只要能够让函数获取所需数据的正确地址,传递什么类型的数据都不要紧——20170626

    9、改变系统图标。。。改rc文件:

    IDI_ICON1               ICON                    "1.ico" 这是ICON                格式                     名称

    10、改变左上坐标this->setWindowIcon().

    有参数的的构造函数的功能之一: NewItem::NewItem(qreal a,qreal b)   为了传递参数。。。。。。 重新构造相应的NewItem,也就是有利于整个程序的信息交流。。。。。

    11、坐标系的问题。

    几何形状发生改变时,会发出resizeEvent这个事件设置resizeEvent();并写入以下内容即可:

    void DiagramWindow::resizeEvent(QResizeEvent * event) { scene->setSceneRect(0,0,this->width(),this->height()); }

    12、设置快捷键

    delitem->setShortcut(Qt::Key_Delete);

    13、error LNK2019: 无法解析的外部符号 "private: void __thiscall DiagramWindow::deleteitem(void)" (?deleteitem@DiagramWindow@@AAEXXZ), 该符号在函数 "private: static void __cdecl DiagramWindow::qt_static_metacall(class QObject *,enum QMetaObject::Call,int,void * *)" (?qt_static_metacall@DiagramWindow@@CAXPAVQObject@@W4Call@QMetaObject@@HPAPAX@Z) 中被引用

    这种错误是由于  函数只有声明没有定义造成的。

    14、最后得到如下视图的图形界面程序QGraphics1.0(有新建,连线,保存,删除,读取等功能)

    再将之前的定时器结合在一起:

    *总之问题还有很多,希望以后能够尽力做到2.0,3.0,4.0吧,以下是问题:

    1、如何自己实现Items的选择和移动? 2、如何提高图标的清晰度? 3、资源管理相关知识是啥?? 4、生成的EXE文件拖到桌面启动,无法工具栏的图标是怎么回事?? 5、QGraphicsScene/View 的图层问题。 6、当QGraphicsScene的窗口大小变化时,怎么改变它的boundingrect()(可能没有??)使得已有的Items能够在 超出预设的范围scene=new QGraphicsScene(0,0,600,500)保存并读取其位置?以及如何当窗口大小改变时,如何 改变已有的Items的坐标和新生成的Items的坐标,即scene坐标系的0点永远在左上.(resizeEvent() 在QMainwindow 的subclass中能够被继承。)

    void DiagramWindow::resizeEvent(QResizeEvent * event) { scene->setSceneRect(0,0,this->width(),this->height()); jishiqi->setGeometry(this->width()-130,this->height()-178,100,220); };//这个可以解决问题6.

    好了总结到此,希望以后做本职工作也要好好地努力,加油!!!

    转载请注明原文地址: https://ju.6miu.com/read-1310273.html
    最新回复(0)