Qt之QDockWidget窗口详解—含演示Demo

前言

        QDockWidget类提供了一个特殊的窗口部件,它可以是被锁在QMainWindow窗口内部或者是作为顶级窗口悬浮在桌面上。
        QDockWidget类提供了dock widget的概念,dock widget也就是我们熟悉的工具面板或者是工具窗口。Dock window是放置在
        QMindow窗口周围的dock widget区域中的

参考博客:QDockWidget详解https://blog.csdn.net/chenlong12580/article/details/9051847       参考代码:Qt\Examples\Qt-5.15.2\widgets\mainwindows

注意:QDockWidget目前只有锁定在QMainWindow窗口内部,才能展现出QDockWidget应有的属性,如果将QDockWidget放到布局管理器当中,那么就只能当作QWidget使用了。

Qt 参考实例当中提供了QMainWindows窗口,看起来也很漂亮,但其实存在这诸多问题。如何要在项目中使用,那么就要进行大量改造。

Qt之QDockWidget窗口详解—含演示Demo_第1张图片

1、QDockWidget常用方法

  常用函数:
  1、addDockWidget:添加停靠控件,用于指定或更改停靠控件的位置以及方向。

void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget * dockwidget)
void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget * dockwidget, Qt::Orientation orientation)

  2、splitDockWidget:分割窗口,用于对两个QDockWidget进行水平或垂直布局。

void QMainWindow::splitDockWidget(QDockWidget * first, QDockWidget * second, Qt::Orientation orientation)

  3、tabifyDockWidget:合并窗口,用于将多个QDockWidget叠加到同一区域。

void QMainWindow::tabifyDockWidget(QDockWidget * first, QDockWidget * second)

  4、setDockNestingEnabled:是否允许嵌套布局

void QMainWindow::setDockNestingEnabled(bool enabled)

2、标题栏 

先上效果图:

2.1、标题栏之最小化,关闭按钮的改造

        Qt默认的最小化,关闭按钮等功能键样式太过复古,已经完全不适应现在用户的审美要求。那么我选择使用Qt无边框属性。将Qt自带的功能键取掉,自己来实现,这样式样可控。

        首先,给QMainWindow添加无边框属性:

this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);

      其次,添加QMenuBar角落小窗口。更多细节代码请下载源码查看。

this->menuBar()->setCornerWidget(m_maxminWin, Qt::TopRightCorner);

注意:QMenuBar角落小窗口在使用上有个小Bug,至今也没有解决,但是可以规避。就是:在窗口的构造函数中添加全屏显示方法,则就看不到角落小窗口。

        那么解决办法是:窗口绘制完成之后,不要显示最大化。这样QMenuBar角落小部件就正常显示出来了。再利用QTimer::Singleshot(), 设置一个很短时间,比如10ms,触发事件,再去this->showMaximized();全屏显示就ok了。

       详情请看Qt社区博客:Qt MainWindow标题栏QMenuBar设置角落小部件失效-CSDN社区https://bbs.csdn.net/topics/606763502

这样就是一个标准的标题栏:包括菜单栏和功能键,样式可控。 

2.2、标题栏之菜单栏

void QDockWidgetDemo::initTitleBar()
{
	QMenuBar* m_MenuBar = this->menuBar();
	m_MenuBar->setStyleSheet(MenuBarStyle);

	QMenu* m_viewMenu = this->menuBar()->addMenu(tr("视图"));
	m_viewMenu->setStyleSheet(MenuStyle);

	m_toolBarAc = new QAction("工具栏");
	connect(m_toolBarAc, &QAction::triggered, this, &QDockWidgetDemo::s_showToolBar);
	m_toolBarAc->setCheckable(true);
	m_toolBarAc->setChecked(true);

	m_projectAc = new QAction("项目");
	connect(m_projectAc, &QAction::triggered, this, &QDockWidgetDemo::s_showPorjectWin);
	m_projectAc->setCheckable(true);
	m_projectAc->setChecked(true);

	m_propertyAc = new QAction("属性");
	connect(m_propertyAc, &QAction::triggered, this, &QDockWidgetDemo::s_showPropertyWin);
	m_propertyAc->setCheckable(true);
	m_propertyAc->setChecked(true);

	m_logAc = new QAction("输出");
	connect(m_logAc, &QAction::triggered, this, &QDockWidgetDemo::s_showLogWin);
	m_logAc->setCheckable(true);
	m_logAc->setChecked(true);

	m_viewMenu->addAction(m_toolBarAc);
	m_viewMenu->addAction(m_projectAc);
	m_viewMenu->addAction(m_propertyAc);
	m_viewMenu->addAction(m_logAc);

	QMenu* m_setView = this->menuBar()->addMenu(tr("设置"));
	QMenu* m_toolMenu = this-> menuBar()->addMenu(tr("工具"));
	QMenu* m_helpMenu = this->menuBar()->addMenu(tr("帮助"));

	initMaxMinWin();
 }

3、QDockWidgets锁定

 在Demo中,QDockWidge窗口实现了工具栏、项目管理区、属性区、日志区等。如图:

Qt之QDockWidget窗口详解—含演示Demo_第2张图片

3.1、工具栏


void QDockWidgetDemo::initToolBar() {
	QSize toolIconSize(50, 30);
	ui.mainToolBar->setIconSize(toolIconSize);   //设置工具栏图标大小

	QIcon newFileIcon(":/images/新建文件.png");
	QIcon openFileIcon(":/images/打开文件.png");
	QIcon saveFileIcon(":/images/保存.png");
	QIcon runIcon(":/images/运行.png");
	QIcon stopIcon(":/images/停止.png");
	QIcon debugIcon(":/images/调试.png");
	QIcon anaysisIcon(":/images/分析.png");
	QIcon recordIcon(":/images/录制.png");
	QIcon grabIcon(":/images/抓取.png");
	QIcon capacityIcon(":/images/应用中心.png");
	QIcon paramterIcon(":/images/参数.png");
	QIcon publishIcon(":/images/发布.png");
	QIcon exportIcon(":/images/导出.png");

	m_newAc = new QAction(newFileIcon, "新建项目", this);
	m_saveAc = new QAction(saveFileIcon, "保存", this);
	m_runAc = new QAction(runIcon, "运行", this);
	m_stopAc = new QAction(stopIcon, "停止", this);
	m_debugAc = new QAction(debugIcon, "调试", this);
	m_anaysisAc = new QAction(anaysisIcon, "分析", this);
	m_recordAc = new QAction(recordIcon, "录制", this);
	m_grabAc = new QAction(grabIcon, "抓取", this);
	m_capacityAc = new QAction(capacityIcon, "能力中心", this);
	m_paramterAc = new QAction(paramterIcon, "参数", this);
	m_publishAc = new QAction(publishIcon, "发布", this);
	m_exportAc = new QAction(exportIcon, "导出", this);

	//add QAction to Widget.
	ui.mainToolBar->addAction(m_newAc);
	ui.mainToolBar->addAction(m_saveAc);
	ui.mainToolBar->addAction(m_saveAc);
	ui.mainToolBar->addSeparator();
	ui.mainToolBar->addAction(m_runAc);
	ui.mainToolBar->addAction(m_stopAc);
	ui.mainToolBar->addAction(m_debugAc);
	ui.mainToolBar->addAction(m_anaysisAc);
	ui.mainToolBar->addSeparator();
	ui.mainToolBar->addAction(m_recordAc);
	ui.mainToolBar->addAction(m_grabAc);
	ui.mainToolBar->addSeparator();
	ui.mainToolBar->addAction(m_capacityAc);
	ui.mainToolBar->addSeparator();
	ui.mainToolBar->addAction(m_paramterAc);
	ui.mainToolBar->addAction(m_publishAc);
	ui.mainToolBar->addAction(m_exportAc);
	ui.mainToolBar->addSeparator();

	connect(m_newAc, &QAction::triggered, this, &QDockWidgetDemo::s_newProject);
	connect(m_saveAc, &QAction::triggered, this, &QDockWidgetDemo::s_saveFile);
	connect(m_runAc, &QAction::triggered, this, &QDockWidgetDemo::s_runAc);
	connect(m_stopAc, &QAction::triggered, this, &QDockWidgetDemo::s_stopAc);
	connect(m_debugAc, &QAction::triggered, this, &QDockWidgetDemo::s_debugAc);
	connect(m_anaysisAc, &QAction::triggered, this, &QDockWidgetDemo::s_anaysisAc);
	connect(m_recordAc, &QAction::triggered, this, &QDockWidgetDemo::s_recordAc);
	connect(m_grabAc, &QAction::triggered, this, &QDockWidgetDemo::s_grabAc);
	connect(m_capacityAc, &QAction::triggered, this, &QDockWidgetDemo::s_capacityAc);
	connect(m_paramterAc, &QAction::triggered, this, &QDockWidgetDemo::s_paramterAc);
	connect(m_publishAc, &QAction::triggered, this, &QDockWidgetDemo::s_publishAc);
	connect(m_exportAc, &QAction::triggered, this, &QDockWidgetDemo::s_exportAc);
}

3.2、项目区

void QDockWidgetDemo::initProjectView() {
	if (NULL == m_projManagerView) {
		m_projManagerView = new QDockWidget(this);
		m_projManagerView->setFeatures(QDockWidget::DockWidgetClosable);    //显示关闭窗口按钮
		m_projManagerView->setWindowTitle("项目");
        this->addDockWidget(Qt::LeftDockWidgetArea, m_projManagerView, Qt::Orientation::Vertical);		 //设置锁定区域

		delete title bar
		//QWidget* lTitleBar = m_projManagerView->titleBarWidget();
		//QWidget* lEmptyWidget = new QWidget();
		//m_projManagerView->setTitleBarWidget(lEmptyWidget);
		//delete lTitleBar;

		m_projectWin = new projectWin(this);
		m_projManagerView->setWidget(m_projectWin);      //添加内容窗口

		qDebug() << "项目区 id:" << m_projManagerView->winId() << ", name:" << m_projManagerView->windowTitle();
	}
}

3.3、属性区

void QDockWidgetDemo::initPropertyView() {
	if (NULL == m_propertyView) {
		m_propertyView = new QDockWidget(this);
		m_propertyView->setFeatures(QDockWidget::DockWidgetClosable);
		m_propertyView->setWindowTitle("属性区");
        this->addDockWidget(Qt::RightDockWidgetArea, m_propertyView, Qt::Orientation::Vertical);

		m_propertyWin = new propertyWin(this);
		m_propertyView->setWidget(m_propertyWin);
		qDebug() << "属性区 id:" << m_propertyView->winId() << ", name:" << m_propertyView->windowTitle();
	}
}

3.4、日志区

void QDockWidgetDemo::initLogView() {
	if (NULL == m_logView) {
		m_logView = new QDockWidget(this);
		//set dock widget feature: not move, enable close.
		m_logView->setFeatures(QDockWidget::DockWidgetClosable);
		m_logView->setWindowTitle("输出");
        this->addDockWidget(Qt::BottomDockWidgetArea, m_logView, Qt::Orientation::Vertical);

		m_logBody = new QTextEdit(this);
		m_logView->setWidget(m_logBody);
	}

	QPalette pl = m_logBody->palette();
	pl.setBrush(QPalette::Base, QBrush(QColor(255, 0, 0, 0)));
	m_logBody->setPalette(pl);
}

4、Demo效果

Qt之QDockWidget窗口详解—含演示Demo_第3张图片

5、Demo下载

        csdn 0积分 下载:Qt之QDockWidget实例Demohttps://download.csdn.net/download/ManagerUser/85496887

6、后期更新方向

6.1 窗口布局调整

Qt之QDockWidget窗口详解—含演示Demo_第4张图片

        我的解决办法是:将(中+低)做成一个整体。那么最外层就只要三个大的窗口:左、中、右。 中间分为:上、下。并且中间窗口继承QMainWindow;上、下两个窗口又是QDockWidget,这样实现了右图的功能要求。

        本方案已经落地实现,效果非常好,并且底部窗口可添加Tab切换按钮,后期有时间上代码。

6.2 QDockWidget窗口默认尺寸调整

         如何调整QDockWidget默认尺寸呢。比如左、右窗口默认太宽,其实可自行调整,并且可调整窗口的最小尺寸。

        调整方案:QDockWidget不能使用resize方法来确定初始大小,如果用setMaximumSize和setFixedSize,的确可以设置初始大小,但也限制了QDockWidget的最大尺寸,不能用鼠标拖动来改变QDockWidget的大小。

派生一个QWidget的新类,设置其sizeHint的返回值

#include   
  
class MyWidget : public QWidget  
{  
public:  
    QSize sizeHint() const  
    {  
        return QSize(270, 900); /* 在这里定义dock的初始大小 */  
    }  
};  
  
int main(int argc, char **argv)  
{  
    QApplication app(argc, argv);  
    QMainWindow box;  
    QDockWidget *dock = new QDockWidget(&box);  
    MyWidget *wi = new MyWidget;  
    dock->setWidget(wi);  
    box.addDockWidget(Qt::TopDockWidgetArea, dock );  
    box.show();  
    return app.exec();      
}  

        以上方案已经得到验证,确实可用。后期有时间,上传一份经过调整的默认尺寸的窗口。

你可能感兴趣的:(Qt专栏,qt,c++,QDockWidget)