博主PyQt5新手,最近在写一个可视化展示界面,第一个遇到的坑就是布局管理。
其实可以不用相对布局,直接用QtDesigner进行傻瓜式的拖控件也不是不可以,高级一点,也可以用绝对布局,定义控件的绝对位置,就可以避免踏入这个坑了。
但是,还是建议大家,尤其是新手使用相对布局,一个感受,就是相对布局美观整齐,控件不会乱。
写在前面
如果大家完全初学,建议大家买本书看看,我发现网上能搜到的关于PyQt5教程都是从书上来的,而且网上的教程都是书本的搬运工,少有自己的思考,比如如何活用布局,也就是这篇博文要解决的内容。建议大家看看《PyQt5快速开发与实战这本书》,总体不错,博主的很多解决方案都是从这本书上来。
下面是编译环境:
- python3.7,编译器是pycharm,特别说明,不要用Spyder,如果只是常规的控件用Spyder没啥问题,但是如果你用了QWebEngineView,会让你崩溃到怀疑人生,遇到的问题无法解决,一度想要从入门到放弃。博主也是从matlab过来的,大爱Spyder的编译风格,但是建议还是趁早换了,pycharm的代码自动填充功能不要太爽;
- 要实现的功能:设置两排横向的按钮,一个网页展示区,和网页并排展示的文本框用来展示数据,展示效果如下:
用到的包
常规包导入
from PyQt5.QtWidgets import * from PyQt5.QtWebEngineWidgets import QWebEngineView from PyQt5.QtCore import Qt, QUrl import sys
QWebEngineView是用来展示百度首页的,用Spyder编译的话,一直会报错,报错如下:
QtWebEngineWidgets must be imported before a QCoreApplication instance is created
界面生成
编写初始化函数,代码如下:
class MyWindow(QWidget): def __init__(self): super(MyWindow,self).__init__() self.setWindowTitle('嵌套布局示例') self.resize(1000, 800) self.browser = QWebEngineView(self) #1 self.textEdit = QTextEdit(self) #2 self.browser_init() #3 self.layout_init() #4 #1 定义一个浏览器控件
#2 定义一个文本编辑框,个人用于展示网页显示的数据
#3 初始化浏览器设置
#4 布局设置
布局设置
不说废话,直接上代码
def layout_init(self): # 全局部件(注意参数 self),用于"承载"全局布局 wwg = QWidget(self) # 全局布局(注意参数 wwg) wl = QVBoxLayout(wwg) hlayout1 = QHBoxLayout() hlayout2 = QHBoxLayout() hlayout3 = QHBoxLayout() #vlayout = QVBoxLayout() #glayout = QGridLayout() #formlayout = QFormLayout() # 局部布局添加部件(例如:按钮) hlayout1.setSpacing(0) #hlayout1.addStretch(1) hlayout1.addWidget( QPushButton(str(1)) ) #hlayout1.addStretch(1) hlayout1.addWidget( QPushButton(str(2)) ) #hlayout1.addStretch(1) hlayout1.addWidget( QPushButton(str(3)) ) #hlayout1.addStretch(1) hlayout1.addWidget( QPushButton(str(4)) ) #hlayout1.addStretch(1) hlayout2.addStretch(1) hlayout2.addWidget( QPushButton(str(1)) ) hlayout2.addStretch(1) hlayout2.addWidget( QPushButton(str(2)) ) hlayout2.addStretch(1) hlayout2.addWidget( QPushButton(str(3)) ) hlayout2.addStretch(1) hlayout2.addWidget( QPushButton(str(4)) ) hlayout2.addStretch(1) #hlayout3.addStretch(1) hlayout3.setSpacing(0) hlayout3.addWidget(self.browser) #hlayout3.addStretch(1) hlayout3.addWidget(self.textEdit) #hlayout3.addStretch(1) #self.setLayout(hlayout) #vlayout.addWidget( QPushButton(str(3)) ) #vlayout.addWidget( QPushButton(str(4)) ) #glayout.addWidget( QPushButton(str(5)) , 0, 0 ) #glayout.addWidget( QPushButton(str(6)) , 0, 1 ) #glayout.addWidget( QPushButton(str(7)) , 1, 0) #glayout.addWidget( QPushButton(str(8)) , 1, 1) #formlayout.addWidget( QPushButton(str(9)) ) #formlayout.addWidget( QPushButton(str(10)) ) #formlayout.addWidget( QPushButton(str(11)) ) #formlayout.addWidget( QPushButton(str(12)) ) # 这里向局部布局内添加部件,将他加到全局布局 wl.addLayout(hlayout1) wl.addLayout(hlayout2) wl.addLayout(hlayout3) #wl.addLayout(vlayout) #wl.addLayout(glayout) #wl.addLayout(formlayout) self.setLayout(wl)
下面对重要代码进行逐行解释:
#wwg = QWidget(self)这里定义了一个全局的布局,接下来,所有的布局都会放在这个布局里进行设置
#wl = QVBoxLayout(wwg)这里将wwg这个全局布局设置为整体的垂直布局,接下来所有的布局都是用的垂直布局
hlayout1 = QHBoxLayout() hlayout2 = QHBoxLayout() hlayout3 = QHBoxLayout()
这里设置三个水平布局,第一个水平布局的控件设置的是按钮,第二个也是按钮,第三个左边是网页,右边是文本编辑框。这三个水平布局按照整体垂直布局从上往下摆放。
下面依次给这三个水平布局添加控件:
第一个水平控件用了setSpacing(0)来设置按钮间距,可以保证按钮从左到右无间距的布满整个横排;
第二个水平控件用了addStretch(1)按比例来分配设置控件后的剩余控件,大家可以看最前面的两排按钮的区别;
第三个水平控件因为想要来放置网页和文本框,所以尽量要布满界面,所以用的是setSpacing(0)进行间距设置。
接下来就是将这三个水平布局添加到整体的垂直布局中去了,用如下的方式:
wl.addLayout(hlayout1) wl.addLayout(hlayout2) wl.addLayout(hlayout3)
self.setLayout(wl)这句代码很关键,书上没有,它的作用是将窗口本身设置为全局布局,如果不写,效果如下:
browser设置默认展示百度首页
我写了个函数,当然也可以直接写在__init__(self)中,不过为了便于理解,建议大家还是写函数
def browser_init(self): self.browser.load(QUrl('https://baidu.com'))
结果展示
是不是以为已经写完了,图样图森破,看看展示成什么鬼样子了
这是什么鬼,为啥左边百度首页展示就这么窄一点点区域,完全不是想要的样子好吗。。。
于是博主一番网上搜索操作,在__init__(self)初始化函数中添加了这么一句代码:
self.textEdit.setFixedWidth(200)
这句代码的作用是将右侧的文本框设置宽度为200,这样就可以了,展示效果就是最上面那张图,如此简单啊。。
学会布局后,就可以随心所欲的添加自己想要的控件了,也完全不用担心美工UI设计出来的花里胡哨的东西了。
当然,博主的开发工作要比这个界面复杂得多,遇到的坑远不止这个布局设置,待相关开发完成后,再一一介绍。
完整代码
最后照旧上完整代码
# -*- coding: utf-8 -*- """ Created on Wed Apr 10 08:52:37 2020 @author: HG """ from PyQt5.QtWidgets import * from PyQt5.QtWebEngineWidgets import QWebEngineView from PyQt5.QtCore import Qt, QUrl import sys class MyWindow(QWidget): def __init__(self): super(MyWindow,self).__init__() self.setWindowTitle('嵌套布局示例') self.resize(1000, 800) self.browser = QWebEngineView(self) self.textEdit = QTextEdit(self) self.browser_init() self.layout_init() self.textEdit.setFixedWidth(200) def layout_init(self): # 全局部件(注意参数 self),用于"承载"全局布局 wwg = QWidget(self) # 全局布局(注意参数 wwg) wl = QVBoxLayout(wwg) hlayout1 = QHBoxLayout() hlayout2 = QHBoxLayout() hlayout3 = QHBoxLayout() #vlayout = QVBoxLayout() #glayout = QGridLayout() #formlayout = QFormLayout() # 局部布局添加部件(例如:按钮) hlayout1.setSpacing(0) #hlayout1.addStretch(1) hlayout1.addWidget( QPushButton(str(1)) ) #hlayout1.addStretch(1) hlayout1.addWidget( QPushButton(str(2)) ) #hlayout1.addStretch(1) hlayout1.addWidget( QPushButton(str(3)) ) #hlayout1.addStretch(1) hlayout1.addWidget( QPushButton(str(4)) ) #hlayout1.addStretch(1) hlayout2.addStretch(1) hlayout2.addWidget( QPushButton(str(1)) ) hlayout2.addStretch(1) hlayout2.addWidget( QPushButton(str(2)) ) hlayout2.addStretch(1) hlayout2.addWidget( QPushButton(str(3)) ) hlayout2.addStretch(1) hlayout2.addWidget( QPushButton(str(4)) ) hlayout2.addStretch(1) #hlayout3.addStretch(1) hlayout3.setSpacing(0) hlayout3.addWidget(self.browser) #hlayout3.addStretch(1) hlayout3.addWidget(self.textEdit) #hlayout3.addStretch(1) #self.setLayout(hlayout) #vlayout.addWidget( QPushButton(str(3)) ) #vlayout.addWidget( QPushButton(str(4)) ) #glayout.addWidget( QPushButton(str(5)) , 0, 0 ) #glayout.addWidget( QPushButton(str(6)) , 0, 1 ) #glayout.addWidget( QPushButton(str(7)) , 1, 0) #glayout.addWidget( QPushButton(str(8)) , 1, 1) #formlayout.addWidget( QPushButton(str(9)) ) #formlayout.addWidget( QPushButton(str(10)) ) #formlayout.addWidget( QPushButton(str(11)) ) #formlayout.addWidget( QPushButton(str(12)) ) # 这里向局部布局内添加部件,将他加到全局布局 wl.addLayout(hlayout1) wl.addLayout(hlayout2) wl.addLayout(hlayout3) #wl.addLayout(vlayout) #wl.addLayout(glayout) #wl.addLayout(formlayout) self.setLayout(wl) def browser_init(self): self.browser.load(QUrl('https://baidu.com')) if __name__=="__main__": app = QApplication(sys.argv) win = MyWindow() win.show() sys.exit(app.exec_())
PyQt5,相对布局
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 【雨果唱片】中国管弦乐《鹿回头》WAV
- APM亚流新世代《一起冒险》[FLAC/分轨][106.77MB]
- 崔健《飞狗》律冻文化[WAV+CUE][1.1G]
- 罗志祥《舞状元 (Explicit)》[320K/MP3][66.77MB]
- 尤雅.1997-幽雅精粹2CD【南方】【WAV+CUE】
- 张惠妹.2007-STAR(引进版)【EMI百代】【WAV+CUE】
- 群星.2008-LOVE情歌集VOL.8【正东】【WAV+CUE】
- 罗志祥《舞状元 (Explicit)》[FLAC/分轨][360.76MB]
- Tank《我不伟大,至少我能改变我。》[320K/MP3][160.41MB]
- Tank《我不伟大,至少我能改变我。》[FLAC/分轨][236.89MB]
- CD圣经推荐-夏韶声《谙2》SACD-ISO
- 钟镇涛-《百分百钟镇涛》首批限量版SACD-ISO
- 群星《继续微笑致敬许冠杰》[低速原抓WAV+CUE]
- 潘秀琼.2003-国语难忘金曲珍藏集【皇星全音】【WAV+CUE】
- 林东松.1997-2039玫瑰事件【宝丽金】【WAV+CUE】