python 圖形界面編程(GUI)


1. Tkinter

在開始GUI編程之前,需要先了解這幾個概念:窗口和控件、事件驅動處理、布局管理器。

  • 窗體控件: 窗體、標簽、按鈕、列表框、滾動條等。
  • 事件驅動:按下按鈕及釋放、鼠標移動、按回車鍵等。
  • 布局管理:Tk有3種布局管理器:Placer、Packer、Grid

1.1 窗體控件

tkinter提供各種控件,如按鈕、標簽和文本框等,在一個GUI應用程序中使用。這些控件有時也被稱為部件。目前有19種tkinter的控件。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-b1LZkyum-1585457939962)(attachment:image.png)]

1.1.1 生成根窗體

from tkinter import *

top = Tk()
top.mainloop()

在這里插入圖片描述

1.1.2 添加標簽

from tkinter import *

top = Tk()
label = Label(top, text = "hello tkinter")
label.pack()
top.mainloop()

在這里插入圖片描述

1.1.3 添加按鈕

from tkinter import *

top = Tk()
label = Label(top, text = "hello tkinter")
button = Button(top ,text="第一個按鈕")
label.pack()
button.pack()
top.mainloop()

在這里插入圖片描述

1.1.4 Checkbutton控件

from tkinter import *


top = Tk()

check_music = IntVar()
check_video = IntVar()

label = Label(top, text = "hello tkinter")
button = Button(top ,text="第一個按鈕")
check_m = Checkbutton(top,text="Music", variable = check_music, onvalue =1, offvalue =0)
check_v = Checkbutton(top,text="Video", variable = check_video, onvalue =1, offvalue =0)

label.pack()
button.pack()
check_m.pack()
check_v.pack()

top.mainloop()

在這里插入圖片描述

1.1.5 Text控件

from tkinter import *


top = Tk()

check_music = IntVar()
check_video = IntVar()

label = Label(top, text = "hello tkinter")
button = Button(top ,text="第一個按鈕")
check_m = Checkbutton(top,text="Music", variable = check_music, onvalue =1, offvalue =0)
check_v = Checkbutton(top,text="Video", variable = check_video, onvalue =1, offvalue =0)

font = ("黑體", 10, "bold")
text = Text(top,height=5, width=30, font=font, bg="white", fg="black")
text.insert(INSERT,"Hello GUI,")
text.insert(END, "Bye!")

label.pack()
button.pack()
check_m.pack()
check_v.pack()
text.pack()

top.mainloop()

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-WmZ1afu7-1585457939966)(attachment:image.png)]

1.1.6 Menu控件

from tkinter import *


win = Tk()
win.title("Python GUI")

def _quit():
    win.quit()
    win.destroy()
    exit()
    
    
    
# 創建菜單欄功能
menuBar = Menu(win) 
win.config(menu = menuBar)

font = ("黑體", 10, "bold")

fileMenu = Menu(menuBar, tearoff=0, font=font, bg="white", fg="black")
menuBar.add_cascade(label="File", menu=fileMenu)
fileMenu.add_command(labe="New File") 
fileMenu.add_separator()
fileMenu.add_command(labe="Exit",command=_quit) 

helpMenu = Menu(menuBar, tearoff=0, font=font, bg="white", fg="black")
menuBar.add_cascade(label="Help", menu=helpMenu)
helpMenu.add_command(labe="About") 

check_music = IntVar()
check_video = IntVar()

label = Label(win, text = "hello tkinter")
button = Button(win ,text="第一個按鈕")
check_m = Checkbutton(win,text="Music", variable = check_music, onvalue =1, offvalue =0)
check_v = Checkbutton(win,text="Video", variable = check_video, onvalue =1, offvalue =0)

text = Text(win,height=5, width=30, font=font, bg="white", fg="black")
text.insert(INSERT,"Hello GUI,")
text.insert(END, "Bye!")

label.pack()
button.pack()
check_m.pack()
check_v.pack()
text.pack()

win .mainloop()

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-7madeizL-1585457939966)(attachment:image.png)]

1.2 實際應用

制作TCP通信的Server 和 Client

# -*- coding: utf-8 -*-
"""
Created on Thu Mar 26 15:34:10 2020

@author: sinlearn
"""
import tkinter as tk
import tkinter.ttk as ttk
import socket
import threading
import time

class TCP_Server():
    def __init__(self):
        winserver = tk.Tk()
        winserver.title("TCP Server")
        winserver.geometry("500x500")
        winserver.resizable(width=False, height=False)
        font = ("宋體", 10)

        self.rbtn = tk.Radiobutton(winserver, text="未連接", fg="red")
        self.label_port = tk.Label(winserver, text=" 端口:", font=font)
        self.label_send = tk.Label(winserver, text=" 發送區:", font=font)
        self.label_recv = tk.Label(winserver, text=" 接收區:", font=font)
        self.label_clist = tk.Label(winserver, text=" 客戶端列表:", font=font)
        self.spinbox_port = tk.Spinbox(winserver, from_=1024, to=10000)
        self.btn_start = tk.Button(winserver, text="啟動", bg="white", command=self.do_start)
        self.btn_stop = tk.Button(winserver, text="停止", bg="white", command=self.do_stop)
        self.btn_send = tk.Button(winserver, text="發送", bg="white", command=self.send_to_client)
        self.en_send = tk.Entry(winserver, text="Test", bd=2)
        self.text_recv = tk.Text(winserver, height=5, width=43, font=font, bg="white", fg="black")
        self.client_list = ttk.Treeview(winserver, height=10, show="headings",
                                        columns=('col1', 'col2', 'col3'))  # show = "headings" 隱藏默認的col0列
        self.client_list.column('col1', width=50, anchor='center')
        self.client_list.column('col2', width=200, anchor='center')
        self.client_list.column('col3', width=100, anchor='center')
        self.client_list.heading('col1', text='序號')
        self.client_list.heading('col2', text='IP地址')
        self.client_list.heading('col3', text='端口號')

        self.rbtn.place(x=10, y=10)
        self.label_port.place(x=100, y=15)
        self.label_send.place(x=100, y=50)
        self.label_recv.place(x=100, y=140)
        self.spinbox_port.place(x=150, y=15)
        self.btn_start.place(x=400, y=10)
        self.btn_stop.place(x=440, y=10)
        self.btn_send.place(x=440, y=70)
        self.en_send.place(x=120, y=70, width=300, height=60)
        self.text_recv.place(x=120, y=160)
        self.label_clist.place(x=100, y=240)
        self.client_list.place(x=120, y=260)

        for i in range(10):
            self.client_list.insert("", i, values=(i, "192.168.2.3" + str(i), "9999"))  # 插入數據
            self.client_list.bind("<Double-1>", self.onDBClick)
        winserver.mainloop()

    def onDBClick(self, event):
        item = self.client_list.selection()[0]
        print("you clicked on ", self.client_list.item(item, "values"))

    def do_start(self):
        self.rbtn["fg"] = "green"
        self.rbtn["text"] = "已連接"
           

    def do_stop(self):
        print("正在斷開連接....")
        self.rbtn["fg"] = "red"
        self.rbtn["text"] = "未連接"
      

    def send_to_client(self):
        if self.rbtn["text"] == "已連接":
            print("正在發送數據....")
        else:
            print("連接未建立,不能發送數據....")

    def tcp_link(self, sock, addr):
        print(f" {addr} 正在請求連接........")
        sock.send("歡迎您連接到服務器........".encode('utf-8'))
        while True:
            data = sock.recv(1024)
            time.sleep(1)
            if data and data.decode('utf-8') != "exit":
                print(data.decode('utf-8'))
                self.text_recv["text"] = data.decode('utf-8')
                sock.send("服務器正在接收數據,請稍等........".encode('utf-8'))
            else:
                break


class TCP_Client():
    def __init__(self):
        self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        winclient = tk.Tk()
        winclient.title("TCP Client")
        winclient.geometry("600x250")
        winclient.resizable(width=False, height=False)
        font = ("宋體", 10)

        self.rbtn = tk.Radiobutton(winclient, text="未連接", fg="red")
        self.label_ip = tk.Label(winclient, text=" IP地址:", font=font)
        self.label_port = tk.Label(winclient, text=" 端口:", font=font)
        self.label_send = tk.Label(winclient, text=" 發送區:", font=font)
        self.label_recv = tk.Label(winclient, text=" 接收區:", font=font)
        self.spinbox_port = tk.Spinbox(winclient, from_=1024, to=10000)
        self.btn_start = tk.Button(winclient, text="連接", bg="white", command=self.do_connect)
        self.btn_stop = tk.Button(winclient, text="斷開", bg="white", command=self.do_stopconnect)
        self.btn_send = tk.Button(winclient, text="發送", bg="white", command=self.send_to_server)
        self.en_ip = tk.Entry(winclient, text="IP地址", bd=2)
        self.en_send = tk.Entry(winclient, text="Test", bd=2)
        self.text_recv = tk.Text(winclient, height=5, width=43, font=font, bg="white", fg="black")

        self.label_ip.place(x=100, y=15)
        self.label_port.place(x=360, y=15)
        self.label_send.place(x=100, y=50)
        self.label_recv.place(x=100, y=150)
        self.rbtn.place(x=10, y=10)
        self.btn_start.place(x=480, y=10)
        self.btn_stop.place(x=520, y=10)
        self.btn_send.place(x=480, y=70)
        self.en_ip.place(x=160, y=15, width=200, height=20)
        self.spinbox_port.place(x=410, y=15, width=50, height=20)
        self.en_send.place(x=120, y=70, width=300, height=60)
        self.text_recv.place(x=120, y=170)
        winclient.mainloop()

    def do_connect(self):
        print("正在連接服務器....")
        self.rbtn["fg"] = "green"
        self.rbtn["text"] = "已連接"
       
    def do_stopconnect(self):
        self.rbtn["fg"] = "red"
        self.rbtn["text"] = "未連接"
       

    def send_to_server(self):
        print("正在往服務器發送數據.....")
        
if __name__ == "__main__":
    TCP_Server()
    TCP_Client()

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-6X2fHhuH-1585457939967)(attachment:image.png)]

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-qXwzDyWE-1585457939968)(attachment:image.png)]

只實現了邏輯,我想具體里面的通信,和socket通信差不多,不繼續寫下去了,真是尷尬。感覺tkinter用起來還是不是很方便。

2. PyQT

2.1 認識PyQT

pyqt5是一套Python綁定Digia QT5應用的框架。它可用於Python 2和3。Qt庫是最強大的GUI庫之一。pyqt5的類別分為幾個模塊,包括以下:

  • QtCore: 包含了核心的非GUI功能。此模塊用於處理時間、文件和目錄、各種數據類型、流、URL、MIME類型、線程或進程。
  • QtGui: 包含類窗口系統集成、事件處理、二維圖形、基本成像、字體和文本。
  • qtwidgets: 包含創造經典桌面風格的用戶界面提供了一套UI元素的類。
  • QtMultimedia: 包含的類來處理多媒體內容和API來訪問相機和收音機的功能。
  • Qtbluetooth: 包含類的掃描設備和連接並與他們互動。描述模塊包含了網絡編程的類。
  • Qtpositioning: 包含類的利用各種可能的來源,確定位置,包括衛星、Wi-Fi、或一個文本文件。
  • Enginio: 實現了客戶端庫訪問Qt雲服務托管的應用程序運行時。
  • Qtwebsockets: 包含實現WebSocket協議類。
  • QtWebKit: 包含一個基於Webkit2圖書館Web瀏覽器實現類。
  • Qtwebkitwidgets: 的類的基礎webkit1一用於qtwidgets應用Web瀏覽器的實現。
  • QtXml: 包含與XML文件的類。這個模塊為SAX和DOM API提供了實現。
  • QtSvg: 提供了顯示SVG文件內容的類。可伸縮矢量圖形(SVG)是一種描述二維圖形和圖形應用的語言。
  • QtSql: 提供操作數據庫的類。
  • QtTest: 包含的功能,使pyqt5應用程序的單元測試

2.2 學習PyQT

如果需要學習該部分的內容可參考:PyQT中文教程:,此處不做過多展開,主要是這個交互式環境,運行這部分代碼,實在,呵呵呵。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM