为什么要自己设计实现标题栏
-
-
无论是使用qtdesigner,还是直接在程序中创建一个Qwidget,qt程序生成的界面都会生成一个默认的标题栏。
-
该标题栏实质上应当是一个边框,只不过这个边框上可以显示ico,标题,可以进行最大化最小化等操作。
-
标题栏的颜色随计算机系统的主题变化,且形式固定,如果为界面设置统一的背景和风格,这个标题栏就会非常的突兀,丑陋。因此,如果想要获得一个和谐的统一的UI界面,我们最好把系统生成的默认标题栏去掉,自己重现默认标题栏附带的功能。
-
--默认标题栏,在统一背景下显得很突兀
想要用自己的就要先去掉别人的
-
-
--QT编程中使用以下语句可以去除系统自动生成的默认边框。
MainWindow::setWindowFlags(Qt::FramelessWindowHint);//隐藏边框
-
-
通过修改setWindowFlags的输入,我们还可以将边框修改成特殊的样式,比如只带一个关闭按钮。
-
--python中该语句的写法为:
self.setWindowFlags(Qt.FramelessWindowHint) # 隐藏边框
去掉标题栏后我们会失去什么
-
-
前文说过,标题栏的本质是一个边框,或者说一个group,这个边框作为限制,UI内容嵌套在边框里,而边框则“悬浮”在桌面上。
-
-
-
因此,去除边框后,首当其冲,UI界面会因为失去边框丢失调整大小的能力,表现出来的就是鼠标无法选中界面的边缘,达到拖动边缘改变大小的目的。
-
同时,因为改变界面在桌面上的位置原本由边框实现,去除边框后,UI与桌面不存在明确的布局关系,界面内容将无法移动。
-
原本程序的最大化(还原),最小化,关闭等功能由标题栏的按钮实现,去除标题栏后,该类操作界面的方式就会消失,不过我们仍可以通过底部状态栏右键操作界面。
-
总结而言,去除标题栏后,我们将无法通过按钮对界面进行最大化(还原),最小化,关闭等操作,无法拖动界面,也无法改变界面的大小,而这些也将是我们后续亟待实现的功能。
-
如何在程序中实现最大化(还原),最小化,关闭等操作
-
-
QT是一个比较傻瓜化的界面绘制方式,针对界面中常备的绘制,关闭等操作,QT架构中有一系列的事件可供调用和修改来帮助编写者较简单的实现这些功能。因此在去除标题栏后,我们仅需要在界面中添加上想要的按钮,命名后放好想要的位置。通过设置风格等方式修改好按钮的样式和标签,我们就能通过调用上文中描述的事件来替代默认标题栏。
1. 放置按钮,调整位置,并修改成自己想要的风格。
-
-
--这里给出一段我常用的按钮样式表,该样式表分别定义了按钮的背景色,鼠标悬浮效果和按下的效果。
QPushButton{background-color:rgba(0,0,0,0);}
QPushButton:hover{background-color:rgba(255,255,255,0.5);}
QPushButton:pressed{background-color: rgba(100,100,100,1);};
2. 准备好符合自己界面风格的各按钮标志,并提前添加到QT的素材文件(.qrc)里。
-
-
--标志应符合界面风格,且应和背景颜色不同,因为我做的暗色界面较多所以这里是纯白色的,没有特殊设计的话这些按钮的背景应当是透明的,我们可以在ps里面很简单的自己绘制一个想要的标志,然后保存为png格式后,再在网上找一个转换的网站转换为ico格式
3. 关闭按钮实现。
-
-
如果不涉及对关闭界面事件的修改,我们仅需在想要的按钮clicked槽函数下调用QT默认的close事件即可。
-
--QT中其调用格式为:
void MainWindow::on_pushButton_close_clicked()
{
MainWindow::close();//关闭事件
}
-
-
--python中,其调用格式更接近信号与槽的格式:
self.pushButton_close.clicked.connect(self.close)
-
-
如果需要修改关闭事件,比如在python多进程编程中需要保证主进程关闭带动子进程一起关闭,则需要对closeevent中内容进行修改。
-
--其在QT中调用格式如下:
void MainWindow::closeEvent(QCloseEvent *event)
{
}
# 关闭主窗口时清理资源
def closeEvent(self, event):
data = "---Visual shield tail clearance measurement system off."
ms = Measurement_data_sava(cctv_par.address, data, forma=4, save_lev=1, log_lev=0)
kill_name(uwb_par.name_pid)
4. 最大化(还原)按钮实现,最小化按钮实现。
void MainWindow::on_pushButton_maximize_clicked()
{
if (MainWindow::isMaximized())
{
MainWindow::showNormal();//还原事件
ui->pushButton_maximize->setIcon(QIcon(QPixmap(":/new/new/max.png")));
}
else
{
MainWindow::showMaximized();//最大化事件
ui->pushButton_maximize->setIcon(QIcon(QPixmap(":/new/new/back.png")));
}
}
-
-
利用MainWindow::isMaximized()可以判断UI界面当前的状态,以分别实现最大化和还原的功能。
-
功能切换时注意更换按钮上显示的标志,以显示其当前真正的功能。
-
--python中最大化(还原)按钮实现方式如下:
# 调用
self.pushButton_max .clicked.connect(self.maxornormale)
# 最大化按钮功能
def maxornormale(self):
if self.isMaximized():
self.flgs_max_normal=0
self.showNormal()
icon7 = QtGui.QIcon()
icon7.addPixmap(QtGui.QPixmap(":/newPrefix/resource/icon/max.png"), QtGui.QIcon.Normal,
QtGui.QIcon.Off)
self.pushButton_max.setIcon(icon7)
else:
self.flgs_max_normal = 1
self.showMaximized()
icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap(":/newPrefix/resource/icon/back.png"), QtGui.QIcon.Normal,
QtGui.QIcon.Off)
self.pushButton_max.setIcon(icon6)
void MainWindow::on_pushButton_minimize_clicked()
{
MainWindow::showMinimized();
}
self.pushButton_min .clicked.connect(self.showMinimized)
实现界面移动
-
-
联想一下,正常情况下界面移动的操作过程是什么?鼠标左键长按标题栏中的非按钮位置,然后拖动鼠标,界面从起始位置移动到鼠标停留的位置。在此过程中,起到定位作用的参数分别有,界面当前的位置,鼠标光标的起始位置,鼠标光标终止位置,起到触发作用则是鼠标左键的长按动作。
-
用QT编程的思路解析该过程,可以表述为:鼠标左键长按作为信号,该信号触发的槽函数为计算操作过程中鼠标位置的变化,再将界面按鼠标位置的变化移动,达成鼠标拖动界面的效果。
-
因此,根据上述分析,鼠标拖动界面移动的实现至少需要两个部分:
1. 识别鼠标的长按动作及落点,长按动作用于触发移动操作,落点则用于判断当前位置应不应该移动界面。
2. 根据记录的鼠标位置,计算出鼠标在桌面坐标系中的变化,再将界面按照变化调整位置。
-
这些动作都可以通过鼠标事件解决。
1. 通过鼠标点击事件,识别鼠标左键按下操作,并记录当前位置:
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
whereismouse=event->pos();
}
}
# 鼠标事件,按下按键
def mousePressEvent(self, e):
if e.buttons() == QtCore.Qt.LeftButton:
try:
self.mos = e.pos()
except:
pass
2. 通过鼠标移动事件,计算鼠标光标的坐标变化,并借助move事件使界面进行相同的移动。
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
if(event->buttons() == Qt::LeftButton)
{
if(MainWindow::isMaximized() || MainWindow::isMinimized())
{
return;
}
else
{
if (ui->groupBox_top->underMouse())
{
if(ui->groupBox_2->underMouse())
{
}
else
{
MainWindow::move(MainWindow::mapToGlobal(event->pos()-whereismouse));
}
}
}
}
event->accept();
}
# 鼠标移动事件
def mouseMoveEvent(self, event):
if self.pushButton_tip.underMouse():
pass
elif self.pushButton_4.underMouse():
pass
elif self.pushButton_5.underMouse():
pass
else:
try:
if event.buttons() == Qt.LeftButton and self.mos:
self.move(self.mapToGlobal(event.pos() - self.mos))
event.accept()
except:
pass
-
-
underMouse()语句可以获取鼠标当前是否悬浮在相应控件上,通过该语句可以控制界面拖动的生效范围,使其不在按钮之类需要鼠标操作的地方误触发。
android shell 安装python python shell安装库
我很想知道一个shell(像 bash,csh 等)内部是如何工作的。于是为了满足自己的好奇心,我使用 Python 实现了一个名为 yosh(Your Own Shell)的 Shell。本文章所介绍的概念也可以应用于其他编程语言。让我们开始吧。步骤 0:项目结构对于此项目,我使用了以下的项目结构。yosh_project
|-- yosh
|-- __init__.py
|-- s
hive 存储为parquet建表 hive创建表指定存储格式
Apache Hive支持Apache Hadoop中使用的几种熟悉的文件格式,如
TextFile,RCFile,SequenceFile,AVRO,ORC和Parquet
格式。Cloudera Impala也支持这些文件格式。 在建表时使用
STORED AS (
TextFile|RCFile|SequenceFile|AVRO|ORC|Parquet
docker desktop 怎么通过命令行启动 docker如何启动
docker可以说给我们的部署带来极大的方便和可逢凶化吉性!(懂的同学自然懂) 在初步了解之后,我们就能简单使用docker了。 刚开始玩docker时,可以基于系统级别的镜像做定制,比如基于 centos 镜像使用docker; docker pull centos:7 # 把镜像拉下来
docker run -it centos:7 # 创建一