天天看點

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)

目錄

1、 QMainWindow視窗

2、QWidget視窗

3、QDialog視窗

3.1、QMessageBox視窗

3.2、QInputDialog視窗

3.3、QFontDialog視窗

3.4、QFileDialog視窗

QMainWindow、QWidget和QDialog三個類都是用來建立視窗的,可以直接使用,也可以繼承後再使用,在Qt Designer建立UI檔案可以選擇這三種視窗類型。

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)

如果是主視窗,就使用QMainWindow類,如果是對話框,就使用QDialog類,如果不确定,或者有可能作為頂層視窗,也有可能嵌入到其他視窗中,那麼就使用QWidget類。 

讓我們看看具體差別吧~

1、 QMainWindow視窗

QMainWindow主視窗為使用者提供一個應用程式架構,它有自己的布局,可以在布局中添加控件。在主視窗中可以添加控件,比如将工具欄、菜單欄和狀态欄等添加到布局管理器中。

QMainWindow類中比較重要的方法如下表所示:

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)

QMainWindow有自己的布局不能設定布局(使用setLayout()方法)。

聊一個實用功能,當主視窗打開運作後,實作預設電腦螢幕居中,效果如下所示:

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)
實作代碼如下所示:

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_())             

以下語句用來設定QWidget視窗的大小,寬度為370像素,高度為250像素。

self.resize(370,  250)             

以下語句用來計算顯示螢幕的大小:(screen.width()*screen.height()),其中

QDesktopWidget是描述顯示螢幕的類,通過QDesktopWidget().screenGeometry()來獲得螢幕的大小。

screen = QDesktopWidget().screenGeometry()           

以下語句用來擷取QWidget視窗的大小:(size.width()*size.heiget())。

size = self.geometry()            

以下語句将視窗移動到螢幕中間。

self.move((screen.width() - size.width()) / 2,  (screen.height() - size.height()) / 2)             

2、QWidget視窗

基礎視窗控件QWidget類是所有使用者界面對象的基類,所有的視窗和控件都直接或間接繼承自QWidget類。

視窗控件(Widget,簡稱“控件”)是在PyQt中建立界面的主要元素。在PyQt中把沒有嵌入到其他控件中的控件稱為視窗,一般視窗都有邊框、标題欄。視窗是指程式的整體界面,可以包含标題欄、菜單欄、工具欄、關閉按鈕、最小化按鈕、最大化按鈕等;控件是指按鈕、複選框、文本框、表格、進度條等這些組成程式的基本元素。一個程式可以有多個視窗,一個視窗也可以有多個控件。

在Qt官方提供的幫助文檔中:“Qt 5.14 Qt Widgets Window and Dialog Widgets”,可見QWidget幾何結構如下所示:

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)

從上圖可以看出,這些成員函數分為三類:

  • QWidget直接提供的成員函數: x()、y()獲得視窗左上角的坐标,width()、 height()獲得客戶區的寬度和高度;
  • QWidget的geometry()提供的成員函數:x()、y()獲得客戶區左上角的坐标,width()、 height()獲得客戶區的寬度和高度;
  • Widget的frameGeometry()提供的成員函數:x()、y()獲得視窗左上角的坐标,width()、 height()獲得包含客戶區、标題欄和邊框在内的整個視窗的寬度和高度。

而且可以知道QWidget有兩種常用的幾何結構:

  • 不包含外邊各種邊框的幾何結構;
  • 包含外邊各種邊框的幾何結構。

1、QWidget不包含邊框的常用函數

一般情況下,不包含邊框的部分是客戶區,這裡面就是我們正常操作的地方,可以添加子控件。這部分是一個長方形,會有大小和位置。大小就是指寬度(width)和高度(height);位置就是指這個長方形在螢幕上的位置。在Qt中儲存這個長方形使用的是QRect類,這個類也有自己的大小和位置。要改變其大小和位置,可以使用如下幾個函數:

  • 改變客戶區的面積

以下兩個函數改變了長方形的大小,其中第一個參數是寬度,第二個參數是高度。設定了大小的視窗,還可以用滑鼠來改變它的大小。

QWidget.resize(width,height)

QWidget.resize(QSize)           
  • 獲得客戶區的大小
Qwidget.size()
           
  • 獲得客戶區的寬度和高度
QWidget.width()

QWidget.height()
           
  •  設定客戶區的寬度和高度

使用這個函數,客戶區的高度就是固定的,不可以改變,隻可以改變寬度。

QWidget.setFixedWidth(int width)           

這時候寬度就是固定的,不可以改變,但是可以改變高度。

QWidget.setFixedHeight(int height)           

以下這兩個函數,高度和寬度都是固定的,不可以通過滑鼠來改變視窗的寬度和高度。

QWidget.setFixedSize(QSize size)

QWidget.setFixedSize(int width,int height)           

如果要同時改變客戶區的大小和位置,需要用到以下函數。

QWidget.setGeometry(int x, int y,int width,int height)

Widget.setGeometry(QRect rect)           

x和y對應的就是x和y坐标,也可以不單獨設定x和y坐标。

2、QWidget包含邊框的常用函數

QWidget包含邊框,這個邊框有大小和位置,是視窗在螢幕上顯示的整個區域。

這裡沒有設定這個邊框大小的函數,因為通過上面不包含邊框函數的設定,就可以設定包含邊框的大小了。通過下面的函數,可以獲得整個視窗的位置和大小。

  • 獲得視窗的大小和位置
QWidget.frameGeometry()           
  • 設定視窗的位置
QWidget.move(int x,int y)

QWidget.move(QPoint point)           
  • 獲得視窗左上角的坐标
QWidget.pos()           

最後将上述函數API整合成一個示例,擷取QWidget控件在螢幕上的坐标,效果如下所示:

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)
from PyQt5.QtWidgets import QApplication  ,QWidget  ,QPushButton
import sys  
              
app = QApplication(sys.argv)
widget = QWidget()
btn = QPushButton( widget )
btn.setText("Button")
#以QWidget左上角為(0, 0)點
btn.move(20, 20)   
#不同作業系統可能對視窗最小寬度有規定,若設定寬度小于規定值,則會以規定值進行顯示
widget.resize(300, 200) 
#以螢幕左上角為(0, 0)點
widget.move(250, 200)

widget.setWindowTitle('PyQt坐标系統例子')
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視窗

為了更好地實作人機互動,比如Windows及Linux等系統均會提供一系列的标準對話框來完成特定場景下的功能,如選擇字号大小、字型顔色等。在PyQt 5中定義了一系列的标準對話框類,讓使用者能夠友善和快捷地通過各個類完成字号大小、字型顔色以及檔案的選擇等。

QDialog是對話框視窗的基類,對話框主要用來執行短期任務,或者與使用者進行互動,它可以是模态的,也可以是非模态的。QDialog視窗沒有菜單欄、工具欄、狀态欄等。

QDialog類中的常用方法如下表所示:

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)

來看一個QDialog視窗的例子,在這個例子中,Dialog視窗的WindowModality屬性決定是否為模态或非模态。單擊QWidget視窗中的PushButton按鈕時,将生成一個對話框視窗。在對話框視窗的标題欄上沒有最小化和最大化控件。代碼中将給按鈕的clicked信号添加槽函數showdialog()。當使用者按下Esc鍵時,對話框視窗将會預設調用QDialog.reject()方法,然後關閉對話框視窗。效果如下所示:

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)
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("彈出對話框")  
		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類的子類主要有QMessageBox、QlnputDialog、QFontDialog、QFileDialog等。來看看它們的特性吧~

QMessageBox是一種通用的彈出式對話框,用于顯示消息,允許使用者通過單擊不同的标準按鈕對消息進行回報。每個标準按鈕都有一個預定義的文本、角色和十六進制數。

QMessageBox類提供了許多常用的彈出式對話框,如提示、警告、錯誤、詢問、關于等對話框。這些不同類型的QMessageBox對話框隻是顯示時的圖示不同,其他功能是—樣的。

QMessageBox類中的常用方法如下表所示:

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)

QMessageBox的标準按鈕類型如下表所示:

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)

5種常用的消息對話框及其顯示效果如下表所示:

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)

以下示例就是QMessageBox的典型應用,效果如下所示:

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)
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("點選彈出消息框")  
		self.myButton.clicked.connect(self.msg)  

	def msg(self):  
        # 使用infomation資訊框  
		reply = QMessageBox.information(self, "标題", "對話框消息正文", QMessageBox.Yes | QMessageBox.No ,  QMessageBox.Yes )  
		print( reply )
		
if __name__ == '__main__':
	app= QApplication(sys.argv)    
	demo = WinForm()  
	demo.show() 
	sys.exit(app.exec_())           

QInputDialog 控件是一個标準對話框,由一個文本框和兩個按鈕(OK按鈕和Cancel按鈕)組成。當使用者單擊OK按鈕或按Enter 鍵後,在父視窗可以收集通過QInputDialog控件輸入的資訊。

QInputDialog控件是QDialog标準對話框的一部分,在QlnputDialog控件中可以輸入數字、字元串或清單中的選項,标簽用于提示必要的資訊。

QlnputDialog類中的常用方法如下表所示:

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)

以下示例就是QFileDialog的典型應用,效果如下所示:

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)
Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)
Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)
Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)

實作代碼如下所示: 

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("獲得清單裡的選項")
		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("獲得整數")
		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",
		"語言清單", 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","輸入數字")
		if ok:
			self.le3.setText(str(num))
					
if __name__ == '__main__':
	app = QApplication(sys.argv)
	demo = InputdialogDemo()
	demo.show()
	sys.exit(app.exec_())           

FontDialog控件是一個常用的字型選擇對話框,可以讓使用者選擇所顯示文本的字号大小、樣式和格式。

QFontDialog 是QDialog 标準對話框的一部分,使用QFontDialog類的靜态方法getFont(),可以從字型選擇對話框中選擇文本的顯示字号大小、樣式和格式。

以下示例就是QFontDialog的典型應用,效果如下所示:

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)

在這個例子中,通過字型選擇對話框選擇相應的字型,并且所選擇字型的效果顯示在QLineEdit的文本上。 實作代碼如下所示: 

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)

        #建立QVBoxLayout布局,在垂直布局管理器中添加fontButton 和fontLineEdit元件,并按照相應的位置添加到栅格布局中。
		layout = QVBoxLayout()
        
		self.fontButton  = QPushButton("choose font")

        #當單擊fontButton按鈕時,将clicked信号發送到槽函數getFont()中。
		self.fontButton .clicked.connect(self.getFont)

        #執行個體化fontButton和fontLineEdit對象,并将fontButton的clicked信号和槽函數getFont()綁定在一起。
		layout.addWidget(self.fontButton )
		self.fontLineEdit  = QLabel("Hello,測試字型例子")
		layout.addWidget(self.fontLineEdit )
		self.setLayout(layout)
		self.setWindowTitle("Font Dialog 例子")
	
    #自定義槽函數,選擇字型,并将字型效果設定到fontLineEdit中。getFont()方法傳回的為元組類型,同時傳回所選擇的字型和函數執行的狀态。
	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_())           

QFileDialog是用于打開和儲存檔案的标準對話框,QFileDialog類繼承自QDialog類。

QFileDialog在打開檔案時使用了檔案過濾器,用于顯示指定擴充名的檔案,也可以設定使用QFileDialog打開檔案時的起始目錄和指定擴充名的檔案。

QFileDialog類中的常用方法如下表所示:

Python Qt GUI設計:QMainWindow、QWidget和QDialog視窗類(基礎篇—10)
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()
        #第一個按鈕使用QFileDialog.getOpenFileNam(),調用檔案對話框來顯示圖像,并顯示在一個标簽控件中。它負責打開C槽目錄下的檔案。
		self.btn = QPushButton("加載圖檔")
		self.btn.clicked.connect(self.getfile)

		layout.addWidget(self.btn)
		self.le = QLabel("")
		layout.addWidget(self.le)

        #第二個按鈕使用檔案對話框(QFileDialog)對象的exec_()方法來選擇檔案,并把所選檔案的内容顯示在文本編輯控件中。
		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_())