QT 开发之旅1

来源:互联网 发布:淘宝优惠券尺寸 编辑:程序博客网 时间:2024/05/23 01:14

第一天的工作

图形编辑器使用多文档结构,所以需要在使用MDI窗口,查了下QT多文档的实现,比较简单:

首先建立主窗口 MainWindow : public QMainWindow。为了实现MDI,必须创建QWorkspace 对象

在构造函数中实现代码

                m_workSpace = new QWorkspace;

setCentralWidget(m_workSpace);
this->setWindowState(Qt::WindowMaximized);
这样就可以了。
然后定义图形页面显示窗口:
class PageView : public QMainWindow
显示子窗口的代码
PageView* pView = new PageView();
    pView->setWindowTitle(QString::fromLocal8Bit("页面窗口"));
    m_workSpace->addWindow(pView);
    pView->show();
想显示中文需QString::fromLocal8Bit("页面窗口"),否则是乱码哦
本来想每个字窗口都带自己的菜单和工具条,使用MDI的合并功能,这样能省下不少功夫,可实际效果很差,所以笨人使用笨办法,菜单和工具条都放到
主窗口上了。用代码Disable,Enable吧。呵呵。
工具条先不做,只用菜单吧,以后加上去,偷偷懒。
菜单,今天就加几个简单的项,文件-打开-新建-保存   绘制-直线-折线-区域  操作-编辑。
先增加图标吧,先增加资源文件,把图标都加进去,运行界面如下:
 
做了这么点工作,今天居然过完了,郁闷啊。什么都没干。
 
今天开始把图形系统显示到子窗口中去
双缓冲显示,QT最好用什么我也不熟悉,先用用图片吧,把我画的图片显示在图片上,然后把图片绘制到窗口上
定义图片 QImage*             m_paintBMP;
定义虚拟窗口 CVirtualVectorForm*m_pForm;因为我自己的图形使用的是自己的窗口系统,现在要在外部使用它就得
定义一个虚拟窗口代替原来的窗口。
void PageView::paintEvent(QPaintEvent* e)中绘制图片
 
if(m_paintBMP == NULL)
    {
        QSize size;
        size = this->size();
        m_paintBMP = new QImage(size,QImage::Format_ARGB32);
        m_paintBMP->fill(0xff123456);
    }
    //绘制页面
    if(m_pForm == NULL)
    {
        QSize size;
        size = this->size();
        m_pForm = CreateVirtualForm(MyVirtualPixOutCallback, MyInvalidateCallback, this, size.width(), size.height());
        InvalidateVirtualForm(m_pForm,0,0,size.width(),size.height());
    }
    VirtualVectorFormDraw(m_pForm, 0, 0, 0, 0);//调用图形系统,绘制图片
   painter.drawImage(0,0,*m_paintBMP);
 
MyInvalidateCallback和MyVirtualPixOutCallback是2个回调函数,MyInvalidateCallback告诉窗口需要重画,MyVirtualPixOutCallback把绘制的
像素输出,PageView对象负责把它写到m_paintBMP中去
void PageView::MyVirtualPixOut(PixPtr pixs,jint32 sizew,jint32 sizeh,jint32 x,jint32 y,jint32 w,jint32 h)
{
    for(int cy = y;cy < (y + h);cy++)
    {
        for(int cx = x;cx < (x + w);cx++)
        {
            if(pixs[cy*sizew + cx].state != 0)
            {
                m_paintBMP->setPixel(cx,cy,pixs[cy*sizew + cx].color);
                pixs[cy*sizew + cx].state = 0;
            }
        }
    }
}
void PageView::MyInvalidate(jint32 x,jint32 y,jint32 w,jint32 h)
{
        this->update();//这里需要优化一下
}
到此为止,图形的显示已经完成了。接下来开始把输入消息传如图形系统
首先是鼠标消息 mouseUp mouseDown mouseMove 对应QT的窗口消息是
void PageView::mousePressEvent(QMouseEvent *event)
{
    if(m_pForm == JNULL)return;
    int bt = 1;
    if(event->button() == Qt::LeftButton)
    {
        bt = 1;
    }
    else if(event->button() == Qt::RightButton)
    {
        bt = 3;
    }
    else if(event->button() == Qt::MidButton)
    {
        bt = 2;
    }
    VirtualVectorFormMouseDown(m_pForm,event->x(),event->y(),bt,0);
}
void PageView::mouseReleaseEvent(QMouseEvent *event)
{
    if(m_pForm == JNULL)return;
    int bt = 1;
    if(event->button() == Qt::LeftButton)
    {
        bt = 1;
    }
    else if(event->button() == Qt::RightButton)
    {
        bt = 3;
    }
    else if(event->button() == Qt::MidButton)
    {
        bt = 2;
    }
    VirtualVectorFormMouseUp(m_pForm,event->x(),event->y(),bt,0);
    VirtualVectorFormMouseClick(m_pForm,event->x(),event->y(),bt,0);
}
void PageView::mouseMoveEvent(QMouseEvent *event)
{
    bool b = this->hasMouseTracking();
    if(m_pForm == JNULL)return;
    VirtualVectorFormMouseMove(m_pForm,event->x(),event->y(),0,0);
}
之前一切比较顺利,可绘制直线的时候发现很乱,跟踪代码的时候发现,原来是mousemove只有在按下鼠标的时候才会触发。有点迷糊,百度大法
原来需要设置MouseTracking属性,在构造函数中调用setMouseTracking(true); 一运行发现还是老样子,不管用,文档上说的很清楚啊
This event handler, for event event, can be reimplemented in a subclass to receive mouse press events for the widget.
If you create new widgets in the mousePressEvent() the mouseReleaseEvent() may not end up where you expect, depending on the underlying window system (or X11 window manager), the widgets' location and maybe more.
The default implementation implements the closing of popup widgets when you click outside the window. For other widget types it does nothing.
怎么回事呢,继续百度 google,终于发现,原来只有基类是QWidget才起作用,赶忙改过来吧
class PageView : public QWidget
终于,一起调试都过了,可以顺利绘制图形了
今天开始做工具条(第4天了)
 
qt工具条做最基本的操作还是蛮方便的,没做过它的自定义控件使用方法,今天刚好要用,收集了部分相关资料,发现实现自定义控件有
2种方法,其一是使用它的接口定义控件,然后可实现控件拖放。第二 和vc是一样的,派生基本控件类,在实例化的时候替换为自己的控件。
目前,第二种方法比较适合我要做的工作:
先 拖个工具条进来,其他工作都的代码实现了,
基本控件,直接用代码加就是了,比较简单,当需要控件布局的时候就和vc不同了,比如坐标x 和y 
 
在头文件中定义:
QGridLayout* m_L_Location;  用它给下面4个控件布局
    QWidget*   m_G_Location;   实际上所有控件都放到它上面,它放到工具条上,相当于把它当做 组 来用
    QLabel*    m_A_Lx_l;   它显示文字
    QLabel*    m_A_Ly_l;它显示文字
    QLineEdit*  m_A_Lx;   它显示X坐标值
    QLineEdit*  m_A_Ly;   它显示y坐标值
 
现在把它加入到工具条中去:
    m_G_Location = new QWidget();
    m_G_Location->setMaximumWidth(150);
    m_L_Location = new QGridLayout(m_G_Location);
    m_L_Location->setMargin(0);
    m_L_Location->setSpacing(0);
    m_A_Lx_l = new QLabel(" X:",m_G_Location);
    m_A_Lx   = new QLineEdit(m_G_Location);
    m_A_Ly_l = new QLabel(" Y:",m_G_Location);
    m_A_Ly   = new QLineEdit(m_G_Location);
 
 m_L_Location->addWidget(m_A_Lx_l,0,0,1,1);
    m_L_Location->addWidget(m_A_Lx,0,1,1,1);
    m_L_Location->addWidget(m_A_Ly_l,1,0,1,1);
    m_L_Location->addWidget(m_A_Ly,1,1,1,1);
    ui->toolBar_Vectoredit->addWidget(m_G_Location);
这样,坐标显示就做好了,现在要做颜色显示,打算用一个下拉box显示颜色和下拉选择颜色,选择颜色的控件采用QColorDialog(不大好用,
好像QT也就只有它了,也许是我没发现吧,不管了,暂时先用着,以后再说)
要达到目的,首先在QComboBox中派生之自己的类
class ColorComboBox : public QComboBox
{
    Q_OBJECT
public:
    ColorComboBox(bool isPen,QWidget *parent = 0);
    void showPopup();      //替换原来要显示的内容
    void hidePopup();
    void on_DialogClosed();
    void on_ColorSelected(QColor c);
    QColor GetColor(){return m_color;}
    void    SetColor(QColor c);
private:
    ComboBoxColorDialog* m_pColorDialog;
    bool                 m_isPen;
    QColor               m_color;
Q_SIGNALS:
    void colorSelected(QColor c);          通知系统,颜色已经发送改变了
protected:
    void paintEvent(QPaintEvent *e);   在上面绘制当前选择的颜色
};
class ComboBoxColorDialog:public QColorDialog
{
    Q_OBJECT
public:
    ComboBoxColorDialog(ColorComboBox* pBox,QWidget *parent);
private:
    ColorComboBox* m_pColorComboBox;
protected:
     void closeEvent(QCloseEvent *event);
 private slots:
     void on_colorSelected ( const QColor & color );
     void on_currentColorChanged ( const QColor & color );
};
ColorComboBox::ColorComboBox(bool isPen,QWidget *parent):QComboBox(parent)
{
    m_pColorDialog = NULL;
    m_isPen = isPen;
    m_color = QColor::fromRgb(0,0,255);
}
 void ColorComboBox::paintEvent(QPaintEvent *e)
 {
     QComboBox::paintEvent(e);
     QPainter painter(this);
     QRect rect = this->rect();
     rect.setSize(QSize(rect.size().width() - 20,rect.size().height() - 4));
     rect.setX(4);
     rect.setY(4);
     if(m_isPen)
     {
         painter.setPen(m_color);
         painter.drawRect(rect);
     }
     else
     {
         QBrush brush(m_color);
         painter.fillRect(rect,brush);
     }
 }
void ColorComboBox::SetColor(QColor c)
{
    m_color = c;
}
void ColorComboBox::showPopup()
{
    if(m_pColorDialog != NULL)
    {
        hidePopup();
        return;
    }
    m_pColorDialog = new ComboBoxColorDialog(this,this->topLevelWidget());
    QPoint pos = this->rect().bottomLeft();
    pos = this->mapToGlobal(pos);
    m_pColorDialog->setOption(QColorDialog::NoButtons);
    m_pColorDialog->move(pos);
    m_pColorDialog->setWindowFlags(Qt::FramelessWindowHint|Qt::Dialog);
    m_pColorDialog->showNormal();
    m_pColorDialog->setFocus();
}
void ColorComboBox::hidePopup()
{
    if(m_pColorDialog != NULL)
    {
        m_pColorDialog->close();
    }
}
void ColorComboBox::on_DialogClosed ( )
{
   m_pColorDialog = NULL;
   this->clearFocus();
}
void ColorComboBox::on_ColorSelected(QColor c)
{
    m_color = c;
    emit colorSelected(c);
    this->update();
}
ComboBoxColorDialog::ComboBoxColorDialog(ColorComboBox* pBox,QWidget *parent):QColorDialog(parent)
 {
    connect(this, SIGNAL(currentColorChanged (const QColor&)), this, SLOT(on_currentColorChanged (const QColor&)));
    connect(this, SIGNAL(colorSelected (const QColor&)), this, SLOT(on_colorSelected (const QColor&)));
    m_pColorComboBox = pBox;
 }
void ComboBoxColorDialog::closeEvent(QCloseEvent *event)
{
    m_pColorComboBox->on_DialogClosed();
}
void ComboBoxColorDialog::on_colorSelected ( const QColor & color )
{
    if(!m_pColorComboBox)return;
    m_pColorComboBox->on_ColorSelected(color);
    this->close();
}
void ComboBoxColorDialog::on_currentColorChanged ( const QColor & color )
{
    if(!m_pColorComboBox)return;
    m_pColorComboBox->on_ColorSelected(color);
    this->close();
}
 
开始使用它:
.h
QGridLayout* m_L_Colors;
QWidget*     m_G_Colors;
QLabel*      m_A_Cp_h;
QLabel*      m_A_Cb_h;
ColorComboBox*   m_A_Cp;
ColorComboBox*   m_A_Cb;
 
.cpp
 m_G_Colors = new QWidget();
    m_G_Colors->setMaximumWidth(150);
    m_L_Colors = new QGridLayout(m_G_Colors);
    m_L_Colors->setMargin(0);
    m_L_Colors->setSpacing(0);
    m_A_Cp_h = new QLabel("",m_G_Colors);
    m_A_Cp_h->setPixmap(QPixmap(QString::fromUtf8(":/images/pen.ico")));
    m_A_Cb_h = new QLabel("",m_G_Colors);
    m_A_Cb_h->setPixmap(QPixmap(QString::fromUtf8(":/images/brush.ico")));
    m_A_Cp   = new ColorComboBox(true,m_G_Colors);
    m_A_Cb   = new ColorComboBox(false,m_G_Colors);
    m_L_Colors->addWidget(m_A_Cp_h,0,0,1,1);
    m_L_Colors->addWidget(m_A_Cp,0,1,1,1);
    m_L_Colors->addWidget(m_A_Cb_h,1,0,1,1);
    m_L_Colors->addWidget(m_A_Cb,1,1,1,1);
    ui->toolBar_Vectoredit->addWidget(m_G_Colors);
    connect(m_A_Cp,SIGNAL( colorSelected(QColor)),this,SLOT(on_PenColorSelected(QColor)));
    connect(m_A_Cb,SIGNAL( colorSelected(QColor)),this,SLOT(on_BrushColorSelected(QColor)));
 
效果看起来不是很好,丑了点,不过已经不是程序问题了,需要休整,现在只是前期,可以暂时不管它
 
现在开始实现了
还需要从QColorDialog上派生一个类,配合使用