qt 中Dialog mainwindow widget 之间的联系和区别

dialog、widget、mainwindow的区别  
    1. dialog有exec函数,如果是dialog窗口,后边的窗口时不可选的;
    2. widget和dialog都有show函数,如果通过这个函数显示这两种类型的窗口,则两个窗口都是可选的;
    3. widget主要是在上面放置布局和控件;
    4. mainwindow可以显示菜单,工具栏,状态栏、托盘等功能。


注意:

1. 查看帮助文档可以发现,setMenuBar、addToolBar、setCentralWidget、setStatusBar几种行为只有QMainWindow类具有。 

因此,在继承自QWidget类的用户类中无法创建菜单栏等几种行为。 

这就是QMainWindow和QWidget的主要区别。

2. QWidget继承于QObject和QPaintDevice,QDialog和QMainWindow则继承于QWidget,QDialog、QMainWindow两者之间没有直接关系。

QWidget
QWidget类是所有用户界面对象的基类。


窗口部件是用户界面的一个原子:它从窗口系统接收鼠标、键盘和其它事件,并且将自己的表现形式绘制在屏幕上。每一个窗口部件都是矩形,并且它们按Z轴顺序排列。一个窗口部件可以被它的父窗口部件或者它前面的窗口部件盖住一部分。


QWidget有很多成员函数,但是它们中的一些有少量的直接功能:例如,QWidget有字体属性,但是自己从来不用。为很多继承它的子类提供了实际的功能,比如QLabel、QPushButton、QCheckBox等等。


没有父窗体的小部件始终是一个独立的窗口(顶级窗口部件)。非窗口的小部件为子部件,它们在父窗口中显示。Qt中大多数部件主要被用作子部件。例如:可以显示一个按钮作为顶层窗口,但大多数人更喜欢将按钮内置于其它部件,如QDialog。


QDialog
QDialog类是对话框窗口的基类。


对话框窗口是一个顶级窗体,主要用于短期任务以及和用户进行简要通讯。QDialog可以是模式的也可以是非模式的。QDialog支持扩展性并且可以提供返回值。它们可以有默认按钮。QDialog也可以有一个QSizeGrip在它的右下角,使用setSizeGripEnabled()。


注意:QDialog(以及其它使用Qt::Dialog类型的widget)使用父窗口部件的方法和Qt中其它类稍微不同。对话框总是顶级窗口部件,但是如果它有一个父对象,它的默认位置就是父对象的中间。它也将和父对象共享工具条条目

#include "mydialog.h"


mydialog::mydialog(QDialog *parent):QDialog(parent) { 

    QPushButton *button = new QPushButton( "button" , this ) ;
    connect( button , SIGNAL(clicked()) , this , SLOT(slotButtonClick()) ) ;
}


void mydialog::slotButtonClick() {

#if 0
    /*dialog和widget的区别,exec和show的区别而已*/
    QDialog *dlg = new QDialog ;
    QPushButton *button = new QPushButton("close" , dlg ) ;
    connect( button , SIGNAL(clicked()) , dlg , SLOT(reject()) ) ;
    int ret = dlg->exec( ) ;
    //通过exec显示出来的窗口称为,模块对话框
    // 在模块对话框中,exec有自己的消息循环,并且把app的消息循环接管了
    // 如果Dialog是通过exec来显示,那么可以通过accept或者reject来关闭窗口
    // 如果Dialog是通过show来显示,那么可以通过close来关闭窗口,这个和QWidget一样的

    // 有许多特殊的dailog:文件选择,MessageBox,颜色选择,字体选择,打印预览,打印
    if( ret == QDialog::Accepted ) 
        qDebug()<<"accepted" ;
    else if( ret== QDialog::Rejected ) 
        qDebug()<<"rejected" ;
#endif 
#if 0
/*文件选择:这个窗口可以选择保存文件的名称,然后将路径+名称返回,我们就可以根据返回路径名来保存文件。*/
    QString strFilename = QFileDialog::getSaveFileName(NULL,
                                                       "Select file for save",
                                                       _strDir,
                                                        "pic file (*.png *.jpg)");
#endif 
#if 0
/*文件选择:选择要打开的文件名(绝对路劲);我们就可以根据这个文件路径来打开相应的文件*/
    QString strFilename = QFileDialog::getOpenFileName(NULL,
                                                       "Select file for open",
                                                       _strDir,
                                                     "pic file (*.png *.jpg)");
#endif
#if 0
    QString strFilename = QFileDialog::getExistingDirectory();

    if(strFilename.isEmpty())
    {
        qDebug() << "select none";
        return;
    }

    qDebug() << strFilename;
    QFileInfo fileInfo(strFilename);
    _strDir = fileInfo.filePath();
    qDebug() << _strDir;
#endif
    //do something for io ... ...
    //上面的选择将绝对路径名都给拿下来了,如果要进行保存,不是很容易吗!
    QPixmap pixmap(this->size()) ;
    QPainter painter(&pixmap) ;
    this->render( &painter ) ;
    pixmap.save(strFilename) ;
#if 0
/*颜色选择对话框:可以选择相应的颜色;然后将选择的颜色返回,这样我们就可以操作了*/
    QColorDialog colorDia ;
    colorDia.exec() ;
    QColor c = colorDia.selectedColor() ;
#endif
#if 0
/*字体选择对话框:可以选择字体;然后将选择的字体信息返回,我们同样可以用这些信息来设置相应的值*/
    QFontDialog fontDia ;
    fontDia.exec() ;
    QFont font = fontDia.selectedFont() ;
#endif
#if 0
/*这个也是弹窗对话框,不过只是简单的选择以下枚举中的值,可以尝试下效果*/
     int ret = QMessageBox::question(this, "????", "realy do .......",
                                    QMessageBox::Yes| QMessageBox::No|
                                    QMessageBox::YesAll| QMessageBox::NoAll);
    if(ret == QMessageBox::Yes)
    {
        qDebug() << "user select yes";
    }
    if(ret == QMessageBox::No)
    {
        qDebug() << "user select no";
    }
    #endif
}


void mydialog::paintEvent( QPaintEvent *ev ) {
}


mydialog::~mydialog(void) { }


模式对话框
阻塞同一应用程序中其它可视窗口输入的对话框。模式对话框有自己的事件循环,用户必须完成这个对话框中的交互操作,并且关闭了它之后才能访问应用程序中的其它任何窗口。模式对话框仅阻止访问与对话相关联的窗口,允许用户继续使用其它窗口中的应用程序。


显示模态对话框最常见的方法是调用其exec()函数,当用户关闭对话框,exec()将提供一个有用的返回值,并且这时流程控制继续从调用exec()的地方进行。通常情况下,要获得对话框关闭并返回相应的值,我们连接默认按钮,例如:”确定”按钮连接到accept()槽,”取消”按钮连接到reject()槽。另外我们也可以连接done()槽,传递给它Accepted或Rejected。


非模式对话框
和同一个程序中其它窗口操作无关的对话框。在文字处理中的查找和替换对话框通常是非模式的,允许用户同时与应用程序的主窗口和对话框进行交互。调用show()来显示非模式对话框,并立即将控制返回给调用者。


如果隐藏对话框后调用show()函数,对话框将显示在其原始位置,这是因为窗口管理器决定的窗户位置没有明确由程序员指定,为了保持被用户移动的对话框位置,在closeEvent()中进行处理,然后在显示之前,将对话框移动到该位置。


半模式对话框
调用setModal(true)或者setWindowModality(),然后show()。有别于exec(),show() 立即返回给控制调用者。


对于进度对话框来说,调用setModal(true)是非常有用的,用户必须拥有与其交互的能力,例如:取消长时间运行的操作。如果使用show()和setModal(true)共同执行一个长时间操作,则必须定期在执行过程中调用QApplication::processEvents(),以使用户能够与对话框交互(可以参考QProgressDialog)。


QMainWindow
QMainWindow类提供一个有菜单条、工具栏、状态条的主应用程序窗口(例如:开发Qt常用的IDE-Visual Studio、Qt Creator等)。


一个主窗口提供了构建应用程序的用户界面框架。Qt拥有QMainWindow及其相关类来管理主窗口。


QMainWindow拥有自己的布局,我们可以使用QMenuBar(菜单栏)、QToolBar(工具栏)、QStatusBar(状态栏)以及QDockWidget(悬浮窗体),布局有一个可由任何种类小窗口所占据的中心区域。

#include "MyWindow.h"


MyWindow::MyWindow(QMainWindow *parent):QMainWindow( parent ) { 

    /*menuBar菜单栏,菜单menu*/
    QMenuBar  *menuBar = this->menuBar() ;
    _menu = menuBar->addMenu( "&File" ) ;
    QMenu *edit = menuBar->addMenu( "&Edit" ) ;

    /*menu菜单中的选项action*/
    QAction *openAction = _menu->addAction( "&Open"
        , this , SLOT(slotOpen()) , QKeySequence::Open  ) ;
    QAction *saveAction = _menu->addAction( "&Save"
        , this , SLOT(slotOpen()) , QKeySequence::Save  ) ;
    _menu->addSeparator() ;//添加分界线
    QAction *closeAction = _menu->addAction( "&Exit"
        , this , SLOT(close()) , QKeySequence::Close  ) ;

    /*toolBar工具栏*/
    QToolBar *toolBar = this->addToolBar( "mimi" ) ;
    toolBar->addAction( openAction ) ;
    toolBar->addAction( saveAction ) ;
    toolBar->addAction( closeAction ) ;
    /*statusBar状态栏*/
    QStatusBar *statusBar = this->statusBar() ;
    QLabel *label ;
    statusBar->addWidget( label = new QLabel("Ok") ) ;
    label->setText( "<font color=blue>XXXXX... ...</font>" ) ;
    /*上面的三种栏介绍完之后,剩下的窗口区域就是CentralWidget
    **如果将widget直接add到mainwindow这个窗口的话,
    **toolbar是会跟添加进来的widget重叠的*/
    MyView *view = new MyView ;
    this->setCentralWidget( view ) ;
    /*最后就是window系统右下脚的托盘:system tray icon*/
    QSystemTrayIcon *icon = new QSystemTrayIcon ;
    icon->setIcon( QIcon("./1.png") ) ;//图标
    icon->setToolTip( "luck dog" ) ;//鼠标滑过提示文字
    icon->show() ;//展示在右下角
    icon->setContextMenu( _menu ) ;//右击出现的菜单
    this->connect( icon , SIGNAL( slotActivated(QSystemTrayIcon::ActivationReason) ) 
        , this , SLOT(slotActivated(QSystemTrayIcon::QSystemTrayIcon::ActivationReason)) ) ;
    this->installEventFilter(this);
}


void MyWindow::slotActivated(QSystemTrayIcon::ActivationReason reason){

    /*这个没成功*/
    if( reason==QSystemTrayIcon::Trigger ) {
        if( this->isHidden() ) 
            this->show() ;
        else
            this->hide() ;
    }
}


bool MyWindow::eventFilter(QObject *o, QEvent *e)
{
    /*实现什么功能呢?*/
    if(o == (QObject*)this && e->type() == QEvent::Close)
    {
        return true;
    }

    return QMainWindow::eventFilter(o, e);
}


void MyWindow::slotOpen() {

    QString fileName = QFileDialog::getOpenFileName() ;
    qDebug()<<fileName ;
    /*将打开的文件中的内容显示在窗口上... ...*/
}
bool MyWindow::event(QEvent *ev)
{
    qDebug() << ev;
    if(ev->type() == QEvent::Close)  {
        return false;
    }
    /*怎么弄才能实现窗口关闭,托盘还在?*/
    return QMainWindow::event(ev);
}


void MyWindow::paintEvent( QPaintEvent * ) {

    QPainter painter(this) ;
    painter.drawPixmap( QPoint(0,0) , QPixmap("./1.png") ) ;
}


void MyWindow::mousePressEvent( QMouseEvent *ev ) {

    if( ev->button() == Qt::RightButton ) {
        _menu->exec( QCursor::pos() ) ;
    }
}


MyWindow::~MyWindow(void) { }




使用原则
如果需要嵌入到其他窗体中,则基于QWidget创建。
如果是顶级对话框,则基于QDialog创建。

如果是主窗体,则基于QMainWindow创建。

参考链接:

https://blog.csdn.net/liang19890820/article/details/50533262

https://blog.csdn.net/a2604539133/article/details/73920696


猜你喜欢

转载自blog.csdn.net/p942005405/article/details/79813448