QMainWindow、QWidget和QDialog三個(gè)類(lèi)都是用來(lái)創(chuàng)建窗口的珍语,可以直接使用锤岸,也可以繼承后再使用,在Qt Designer創(chuàng)建UI文件可以選擇這三種窗口類(lèi)型板乙。
如果是主窗口是偷,就使用QMainWindow類(lèi),如果是對(duì)話(huà)框募逞,就使用QDialog類(lèi)蛋铆,如果不確定,或者有可能作為頂層窗口放接,也有可能嵌入到其他窗口中刺啦,那么就使用QWidget類(lèi)。
讓我們看看具體區(qū)別吧~
1纠脾、 QMainWindow窗口
QMainWindow主窗口為用戶(hù)提供一個(gè)應(yīng)用程序框架玛瘸,它有自己的布局蜕青,可以在布局中添加控件。在主窗口中可以添加控件糊渊,比如將工具欄右核、菜單欄和狀態(tài)欄等添加到布局管理器中。
QMainWindow類(lèi)中比較重要的方法如下表所示:
QMainWindow有自己的布局不能設(shè)置布局(使用setLayout()方法)渺绒。
聊一個(gè)實(shí)用功能贺喝,當(dāng)主窗口打開(kāi)運(yùn)行后,實(shí)現(xiàn)默認(rèn)電腦屏幕居中芒篷,效果如下所示:
實(shí)現(xiàn)代碼如下所示:
from PyQt5.QtWidgets import QDesktopWidget, QApplication ,QMainWindow
import sys?
class Winform( QMainWindow):
? ? def __init__(self, parent=None):
? ? ? ? super( Winform, self).__init__(parent)
? ? ? ? self.setWindowTitle('主窗口放在屏幕中間例子')?
? ? ? ? self.resize(370,? 250)?
? ? ? ? self.center()?
? ? def center(self):?
? ? ? ? screen = QDesktopWidget().screenGeometry()?
? ? ? ? size = self.geometry()? ? ? ?
? ? ? ? self.move((screen.width() - size.width()) / 2,? (screen.height() - size.height()) / 2)?
if __name__ == "__main__":
? ? app = QApplication(sys.argv)?
? ? win = Winform()?
? ? win.show()?
? ? sys.exit(app.exec_())?
以下語(yǔ)句用來(lái)設(shè)置QWidget窗口的大小搜变,寬度為370像素采缚,高度為250像素针炉。
self.resize(370,? 250)?
以下語(yǔ)句用來(lái)計(jì)算顯示屏幕的大小:(screen.width()*screen.height())扳抽,其中
QDesktopWidget是描述顯示屏幕的類(lèi)篡帕,通過(guò)QDesktopWidget().screenGeometry()來(lái)獲得屏幕的大小。
screen = QDesktopWidget().screenGeometry()
以下語(yǔ)句用來(lái)獲取QWidget窗口的大忻衬亍:(size.width()*size.heiget())镰烧。
size = self.geometry()
以下語(yǔ)句將窗口移動(dòng)到屏幕中間。
self.move((screen.width() - size.width()) / 2,? (screen.height() - size.height()) / 2)?
2楞陷、QWidget窗口
基礎(chǔ)窗口控件QWidget類(lèi)是所有用戶(hù)界面對(duì)象的基類(lèi)怔鳖,所有的窗口和控件都直接或間接繼承自QWidget類(lèi)。
窗口控件(Widget固蛾,簡(jiǎn)稱(chēng)“控件”)是在PyQt中建立界面的主要元素结执。在PyQt中把沒(méi)有嵌入到其他控件中的控件稱(chēng)為窗口,一般窗口都有邊框艾凯、標(biāo)題欄献幔。窗口是指程序的整體界面,可以包含標(biāo)題欄趾诗、菜單欄蜡感、工具欄、關(guān)閉按鈕恃泪、最小化按鈕郑兴、最大化按鈕等;控件是指按鈕贝乎、復(fù)選框杈笔、文本框、表格糕非、進(jìn)度條等這些組成程序的基本元素蒙具。一個(gè)程序可以有多個(gè)窗口球榆,一個(gè)窗口也可以有多個(gè)控件。
在Qt官方提供的幫助文檔中:“Qt 5.14 Qt Widgets Window and Dialog Widgets”禁筏,可見(jiàn)QWidget幾何結(jié)構(gòu)如下所示:
從上圖可以看出持钉,這些成員函數(shù)分為三類(lèi):
QWidget直接提供的成員函數(shù): x()、y()獲得窗口左上角的坐標(biāo)篱昔,width()每强、 height()獲得客戶(hù)區(qū)的寬度和高度;
QWidget的geometry()提供的成員函數(shù):x()州刽、y()獲得客戶(hù)區(qū)左上角的坐標(biāo)空执,width()、 height()獲得客戶(hù)區(qū)的寬度和高度穗椅;
Widget的frameGeometry()提供的成員函數(shù):x()辨绊、y()獲得窗口左上角的坐標(biāo),width()匹表、 height()獲得包含客戶(hù)區(qū)门坷、標(biāo)題欄和邊框在內(nèi)的整個(gè)窗口的寬度和高度。
而且可以知道QWidget有兩種常用的幾何結(jié)構(gòu):
不包含外邊各種邊框的幾何結(jié)構(gòu)袍镀;
包含外邊各種邊框的幾何結(jié)構(gòu)默蚌。
1、QWidget不包含邊框的常用函數(shù)
一般情況下苇羡,不包含邊框的部分是客戶(hù)區(qū)绸吸,這里面就是我們正常操作的地方,可以添加子控件设江。這部分是一個(gè)長(zhǎng)方形锦茁,會(huì)有大小和位置。大小就是指寬度(width)和高度(height)绣硝;位置就是指這個(gè)長(zhǎng)方形在屏幕上的位置蜻势。在Qt中保存這個(gè)長(zhǎng)方形使用的是QRect類(lèi),這個(gè)類(lèi)也有自己的大小和位置鹉胖。要改變其大小和位置握玛,可以使用如下幾個(gè)函數(shù):
改變客戶(hù)區(qū)的面積
以下兩個(gè)函數(shù)改變了長(zhǎng)方形的大小,其中第一個(gè)參數(shù)是寬度甫菠,第二個(gè)參數(shù)是高度挠铲。設(shè)置了大小的窗口寂诱,還可以用鼠標(biāo)來(lái)改變它的大小拂苹。
QWidget.resize(width,height)
QWidget.resize(QSize)
獲得客戶(hù)區(qū)的大小
Qwidget.size()
獲得客戶(hù)區(qū)的寬度和高度
QWidget.width()
QWidget.height()
設(shè)置客戶(hù)區(qū)的寬度和高度
使用這個(gè)函數(shù),客戶(hù)區(qū)的高度就是固定的痰洒,不可以改變瓢棒,只可以改變寬度浴韭。
QWidget.setFixedWidth(int width)
這時(shí)候?qū)挾染褪枪潭ǖ模豢梢愿淖兏蓿强梢愿淖兏叨取?/p>
QWidget.setFixedHeight(int height)
以下這兩個(gè)函數(shù)念颈,高度和寬度都是固定的,不可以通過(guò)鼠標(biāo)來(lái)改變窗口的寬度和高度连霉。
QWidget.setFixedSize(QSize size)
QWidget.setFixedSize(int width,int height)
如果要同時(shí)改變客戶(hù)區(qū)的大小和位置榴芳,需要用到以下函數(shù)。
QWidget.setGeometry(int x, int y,int width,int height)
Widget.setGeometry(QRect rect)
x和y對(duì)應(yīng)的就是x和y坐標(biāo)跺撼,也可以不單獨(dú)設(shè)置x和y坐標(biāo)窟感。
2、QWidget包含邊框的常用函數(shù)
QWidget包含邊框歉井,這個(gè)邊框有大小和位置柿祈,是窗口在屏幕上顯示的整個(gè)區(qū)域。
這里沒(méi)有設(shè)置這個(gè)邊框大小的函數(shù)酣难,因?yàn)橥ㄟ^(guò)上面不包含邊框函數(shù)的設(shè)置谍夭,就可以設(shè)置包含邊框的大小了黑滴。通過(guò)下面的函數(shù)憨募,可以獲得整個(gè)窗口的位置和大小。
獲得窗口的大小和位置
QWidget.frameGeometry()
設(shè)置窗口的位置
QWidget.move(int x,int y)
QWidget.move(QPoint point)
獲得窗口左上角的坐標(biāo)
QWidget.pos()
最后將上述函數(shù)API整合成一個(gè)示例袁辈,獲取QWidget控件在屏幕上的坐標(biāo)菜谣,效果如下所示:
實(shí)現(xiàn)代碼如下所示:
from PyQt5.QtWidgets import QApplication? ,QWidget? ,QPushButton
import sys?
app = QApplication(sys.argv)
widget = QWidget()
btn = QPushButton( widget )
btn.setText("Button")
#以QWidget左上角為(0, 0)點(diǎn)
btn.move(20, 20)?
#不同操作系統(tǒng)可能對(duì)窗口最小寬度有規(guī)定,若設(shè)置寬度小于規(guī)定值晚缩,則會(huì)以規(guī)定值進(jìn)行顯示
widget.resize(300, 200)
#以屏幕左上角為(0, 0)點(diǎn)
widget.move(250, 200)
widget.setWindowTitle('PyQt坐標(biāo)系統(tǒng)例子')
widget.show()
print("#1 QWidget")
print("widget.x()=%d" % widget.x() )
print("widget.y()=%d" % widget.y() )
print("widget.width()=%d" % widget.width() )
print("widget.height()=%d" % widget.height() )
print("#2 QWidget.geometry")
print("widget.geometry().x()=%d" %? widget.geometry().x() )
print("widget.geometry().y()=%d" %? widget.geometry().y() )
print("widget.geometry().width()=%d" %? widget.geometry().width() )
print("widget.geometry().height()=%d" %? widget.geometry().height() )
print("widget.size().width() =%d" %? widget.size().width() )
print("widget.size().height() =%d" %? widget.size().height() )
print("#3 QWidget.frameGeometry")
print("widget.frameGeometry().width()=%d" %? widget.frameGeometry().width() )
print("widget.frameGeometry().height()=%d" %? widget.frameGeometry().height() )
print("widget.pos().x()=%d" %? widget.pos().x() )
print("widget.pos().y()=%d" %? widget.pos().y() )
sys.exit(app.exec_())?
3尾膊、QDialog窗口
為了更好地實(shí)現(xiàn)人機(jī)交互,比如Windows及Linux等系統(tǒng)均會(huì)提供一系列的標(biāo)準(zhǔn)對(duì)話(huà)框來(lái)完成特定場(chǎng)景下的功能荞彼,如選擇字號(hào)大小冈敛、字體顏色等。在PyQt 5中定義了一系列的標(biāo)準(zhǔn)對(duì)話(huà)框類(lèi)鸣皂,讓使用者能夠方便和快捷地通過(guò)各個(gè)類(lèi)完成字號(hào)大小抓谴、字體顏色以及文件的選擇等。
QDialog是對(duì)話(huà)框窗口的基類(lèi)寞缝,對(duì)話(huà)框主要用來(lái)執(zhí)行短期任務(wù)癌压,或者與用戶(hù)進(jìn)行互動(dòng),它可以是模態(tài)的荆陆,也可以是非模態(tài)的滩届。QDialog窗口沒(méi)有菜單欄、工具欄被啼、狀態(tài)欄等帜消。
QDialog類(lèi)中的常用方法如下表所示:
來(lái)看一個(gè)QDialog窗口的例子棠枉,在這個(gè)例子中,Dialog窗口的WindowModality屬性決定是否為模態(tài)或非模態(tài)泡挺。單擊QWidget窗口中的PushButton按鈕時(shí)术健,將生成一個(gè)對(duì)話(huà)框窗口。在對(duì)話(huà)框窗口的標(biāo)題欄上沒(méi)有最小化和最大化控件粘衬。代碼中將給按鈕的clicked信號(hào)添加槽函數(shù)showdialog()荞估。當(dāng)用戶(hù)按下Esc鍵時(shí),對(duì)話(huà)框窗口將會(huì)默認(rèn)調(diào)用QDialog.reject()方法稚新,然后關(guān)閉對(duì)話(huà)框窗口勘伺。效果如下所示:
實(shí)現(xiàn)代碼如下所示:
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class DialogDemo( QMainWindow ):
def __init__(self, parent=None):
super(DialogDemo, self).__init__(parent)
self.setWindowTitle("Dialog 例子")
self.resize(350,300)
self.btn = QPushButton( self)
self.btn.setText("彈出對(duì)話(huà)框")?
self.btn.move(50,50)
self.btn.clicked.connect(self.showdialog)?
def showdialog(self ):
dialog = QDialog()
btn = QPushButton("ok", dialog )
btn.move(50,50)
dialog.setWindowTitle("Dialog")
dialog.setWindowModality(Qt.ApplicationModal)
dialog.exec_()
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = DialogDemo()
demo.show()
sys.exit(app.exec_())
QDialog類(lèi)的子類(lèi)主要有QMessageBox、QlnputDialog褂删、QFontDialog飞醉、QFileDialog等。來(lái)看看它們的特性吧~
3.1屯阀、QMessageBox窗口
QMessageBox是一種通用的彈出式對(duì)話(huà)框缅帘,用于顯示消息,允許用戶(hù)通過(guò)單擊不同的標(biāo)準(zhǔn)按鈕對(duì)消息進(jìn)行反饋难衰。每個(gè)標(biāo)準(zhǔn)按鈕都有一個(gè)預(yù)定義的文本钦无、角色和十六進(jìn)制數(shù)。
QMessageBox類(lèi)提供了許多常用的彈出式對(duì)話(huà)框盖袭,如提示失暂、警告、錯(cuò)誤鳄虱、詢(xún)問(wèn)弟塞、關(guān)于等對(duì)話(huà)框。這些不同類(lèi)型的QMessageBox對(duì)話(huà)框只是顯示時(shí)的圖標(biāo)不同拙已,其他功能是—樣的决记。
QMessageBox類(lèi)中的常用方法如下表所示:
QMessageBox的標(biāo)準(zhǔn)按鈕類(lèi)型如下表所示:
5種常用的消息對(duì)話(huà)框及其顯示效果如下表所示:
以下示例就是QMessageBox的典型應(yīng)用,效果如下所示:
實(shí)現(xiàn)代碼如下所示:
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class WinForm( QWidget):?
def __init__(self):?
super(WinForm,self).__init__()?
self.setWindowTitle("QMessageBox 例子")?
self.resize(300, 100)? ? ? ? ? ? ?
self.myButton = QPushButton(self)? ?
self.myButton.setText("點(diǎn)擊彈出消息框")?
self.myButton.clicked.connect(self.msg)?
def msg(self):?
? ? ? ? # 使用infomation信息框?
reply = QMessageBox.information(self, "標(biāo)題", "對(duì)話(huà)框消息正文", QMessageBox.Yes | QMessageBox.No ,? QMessageBox.Yes )?
print( reply )
if __name__ == '__main__':
app= QApplication(sys.argv)? ?
demo = WinForm()?
demo.show()
sys.exit(app.exec_())
3.2倍踪、QInputDialog窗口
QInputDialog 控件是一個(gè)標(biāo)準(zhǔn)對(duì)話(huà)框系宫,由一個(gè)文本框和兩個(gè)按鈕(OK按鈕和Cancel按鈕)組成。當(dāng)用戶(hù)單擊OK按鈕或按Enter 鍵后惭适,在父窗口可以收集通過(guò)QInputDialog控件輸入的信息笙瑟。
QInputDialog控件是QDialog標(biāo)準(zhǔn)對(duì)話(huà)框的一部分,在QlnputDialog控件中可以輸入數(shù)字癞志、字符串或列表中的選項(xiàng)往枷,標(biāo)簽用于提示必要的信息。
QlnputDialog類(lèi)中的常用方法如下表所示:
以下示例就是QFileDialog的典型應(yīng)用,效果如下所示:
實(shí)現(xiàn)代碼如下所示:
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class InputdialogDemo(QWidget):
def __init__(self, parent=None):
super(InputdialogDemo, self).__init__(parent)
layout = QFormLayout()
self.btn1 = QPushButton("獲得列表里的選項(xiàng)")
self.btn1.clicked.connect(self.getItem)
self.le1 = QLineEdit()
layout.addRow(self.btn1,self.le1)
self.btn2 = QPushButton("獲得字符串")
self.btn2.clicked.connect(self.getIext)
self.le2 = QLineEdit()
layout.addRow(self.btn2,self.le2)
self.btn3 = QPushButton("獲得整數(shù)")
self.btn3.clicked.connect(self.getInt)
self.le3 = QLineEdit()
layout.addRow(self.btn3,self.le3)
self.setLayout(layout)
self.setWindowTitle("Input Dialog 例子")
def getItem(self):
items = ("C", "C++", "Java", "Python")
item, ok = QInputDialog.getItem(self, "select input dialog",
"語(yǔ)言列表", items, 0, False)
if ok and item:
self.le1.setText(item)
def getIext(self):
text, ok = QInputDialog.getText(self, 'Text Input Dialog', '輸入姓名:')
if ok:
self.le2.setText(str(text))
def getInt(self):
num,ok = QInputDialog.getInt(self,"integer input dualog","輸入數(shù)字")
if ok:
self.le3.setText(str(num))
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = InputdialogDemo()
demo.show()
sys.exit(app.exec_())
3.3错洁、QFontDialog窗口
FontDialog控件是一個(gè)常用的字體選擇對(duì)話(huà)框秉宿,可以讓用戶(hù)選擇所顯示文本的字號(hào)大小、樣式和格式屯碴。
QFontDialog 是QDialog 標(biāo)準(zhǔn)對(duì)話(huà)框的一部分描睦,使用QFontDialog類(lèi)的靜態(tài)方法getFont(),可以從字體選擇對(duì)話(huà)框中選擇文本的顯示字號(hào)大小导而、樣式和格式忱叭。
以下示例就是QFontDialog的典型應(yīng)用,效果如下所示:
在這個(gè)例子中今艺,通過(guò)字體選擇對(duì)話(huà)框選擇相應(yīng)的字體韵丑,并且所選擇字體的效果顯示在QLineEdit的文本上。 實(shí)現(xiàn)代碼如下所示:
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class FontDialogDemo(QWidget):
def __init__(self, parent=None):
super(FontDialogDemo, self).__init__(parent)
? ? ? ? #創(chuàng)建QVBoxLayout布局虚缎,在垂直布局管理器中添加fontButton 和fontLineEdit組件撵彻,并按照相應(yīng)的位置添加到柵格布局中。
layout = QVBoxLayout()
self.fontButton? = QPushButton("choose font")
? ? ? ? #當(dāng)單擊fontButton按鈕時(shí)实牡,將clicked信號(hào)發(fā)送到槽函數(shù)getFont()中陌僵。
self.fontButton .clicked.connect(self.getFont)
? ? ? ? #實(shí)例化fontButton和fontLineEdit對(duì)象,并將fontButton的clicked信號(hào)和槽函數(shù)getFont()綁定在一起创坞。
layout.addWidget(self.fontButton )
self.fontLineEdit? = QLabel("Hello,測(cè)試字體例子")
layout.addWidget(self.fontLineEdit )
self.setLayout(layout)
self.setWindowTitle("Font Dialog 例子")
? ? #自定義槽函數(shù)碗短,選擇字體,并將字體效果設(shè)置到fontLineEdit中摆霉。getFont()方法返回的為元組類(lèi)型豪椿,同時(shí)返回所選擇的字體和函數(shù)執(zhí)行的狀態(tài)奔坟。
def getFont(self):
font, ok = QFontDialog.getFont()
if ok:
self.fontLineEdit .setFont(font)
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = FontDialogDemo()
demo.show()
sys.exit(app.exec_())
3.4携栋、QFileDialog窗口
QFileDialog是用于打開(kāi)和保存文件的標(biāo)準(zhǔn)對(duì)話(huà)框,QFileDialog類(lèi)繼承自QDialog類(lèi)咳秉。
QFileDialog在打開(kāi)文件時(shí)使用了文件過(guò)濾器婉支,用于顯示指定擴(kuò)展名的文件,也可以設(shè)置使用QFileDialog打開(kāi)文件時(shí)的起始目錄和指定擴(kuò)展名的文件澜建。
QFileDialog類(lèi)中的常用方法如下表所示:
在這個(gè)例子中向挖,通過(guò)文件對(duì)話(huà)框來(lái)選擇文件,其中第一個(gè)文件對(duì)話(huà)框只允許打開(kāi)圖片文件炕舵,并把所加載的圖片顯示在標(biāo)簽(QLabel)中何之;第二個(gè)文件對(duì)話(huà)框只允許打開(kāi)文本文件,并把文本內(nèi)容顯示在文本框(QTextEdit)內(nèi)咽筋。 實(shí)現(xiàn)代碼如下所示:
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class filedialogdemo(QWidget):
def __init__(self, parent=None):
super(filedialogdemo, self).__init__(parent)
layout = QVBoxLayout()
? ? ? ? #第一個(gè)按鈕使用QFileDialog.getOpenFileNam()溶推,調(diào)用文件對(duì)話(huà)框來(lái)顯示圖像,并顯示在一個(gè)標(biāo)簽控件中。它負(fù)責(zé)打開(kāi)C盤(pán)目錄下的文件蒜危。
self.btn = QPushButton("加載圖片")
self.btn.clicked.connect(self.getfile)
layout.addWidget(self.btn)
self.le = QLabel("")
layout.addWidget(self.le)
? ? ? ? #第二個(gè)按鈕使用文件對(duì)話(huà)框(QFileDialog)對(duì)象的exec_()方法來(lái)選擇文件虱痕,并把所選文件的內(nèi)容顯示在文本編輯控件中。
self.btn1 = QPushButton("加載文本文件")
self.btn1.clicked.connect(self.getfiles)
layout.addWidget(self.btn1)
self.contents = QTextEdit()
layout.addWidget(self.contents)
self.setLayout(layout)
self.setWindowTitle("File Dialog 例子")
def getfile(self):
fname, _? = QFileDialog.getOpenFileName(self, 'Open file', 'c:\\',"Image files (*.jpg *.gif)")
self.le.setPixmap(QPixmap(fname))
def getfiles(self):
dlg = QFileDialog()
dlg.setFileMode(QFileDialog.AnyFile)
dlg.setFilter( QDir.Files? )
if dlg.exec_():
filenames= dlg.selectedFiles()
f = open(filenames[0], 'r')
with f:
data = f.read()
self.contents.setText(data)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = filedialogdemo()
ex.show()
sys.exit(app.exec_())