GUI

Table of Contents

Hits #+HTML_HEAD_EXTRA:

1. Streamlit

Streamlit 是一個開源的 Python 庫,專為數據科學家、機器學習工程師和開發者設計,能夠快速構建美觀且功能強大的網頁應用程式。它最大的優勢在於不需要複雜的前端開發技術,只需用簡單的 Python 代碼即可生成互動式的網頁應用。Streamlit 常被用於展示數據分析結果、機器學習模型或交互式儀表板。

1.1. 特點:

  • 簡單易用:只需要使用 Python 代碼,無需學習 HTML、CSS 或 JavaScript 等前端技術。
  • 快速開發:用戶可以在幾分鐘內從數據分析轉變成一個全功能的網頁應用,適合快速開發與迭代。
  • 實時互動:用戶可以通過滑桿、下拉選單等組件與數據進行交互,實時更新視覺化結果。
  • 即時更新:任何對代碼的變更在保存後會自動刷新網頁,允許用戶快速查看變化。

1.2. 適用場景:

  • 數據展示與可視化:簡單地展示數據分析結果,通過圖表和文字解說進行報告。
  • 機器學習應用展示:使用 Streamlit 可以輕鬆將機器學習模型包裝成一個可操作的網頁工具,讓非技術人員也能進行模型預測。
  • 交互式儀表板:創建類似於 BI(商業智能)的儀表板,用於動態數據的展示與控制。

1.3. 安裝套件

1.3.1. 1. 使用前先安裝套件

1: pip3 install streamlit

1.3.2. 2. 利用pycharm或其他編輯器新增一個python程式碼,檔名先叫main.py,輸入下列程式、存檔

1: import streamlit as st
2: 
3: st.title('測試python的web玩具')

1.3.3. 3. 執行

在pycharm、visual code裡的終端機輸入以下指令

1: streamlit run main.py

1.3.4. 結果

2024-07-24_13-58-48_2024-07-24_13-58-19.png

Figure 1: Streamlit 執行畫面

1.4. Run Streamlit code in Google Colab

1.4.1. 安裝streamlit

1: !pip install streamlit -q

1.4.2. 取得外部IP

The second line (!wget -q -O - ipv4.icanhazip.com) retrieves your external IP address using the wget command.

1: !wget -q -O - ipv4.icanhazip.com

1.4.3. 生成app.py

The line %%writefile app.py writes the Streamlit app code to a file named app.py. The Streamlit app itself is a simple calculator. It takes two input numbers, adds them together, and displays the result.

1: %%writefile app.py
2: import streamlit as st
3: st.write('#Streamlit計算機')
4: num1 = st.number_input('數字1')
5: num2 = st.number_input('數字2')
6: num3 = num1 + num2
7: st.write('#答案', num3)
8: 
9: write app.py

1.4.4. 執行app.py

The line !streamlit run app.py & runs the Streamlit app in the background. The & at the end allows the Colab notebook to continue executing other cells without waiting for the Streamlit app to finish.

!npx localtunnel –port 8501 uses npx localtunnel to expose the locally running Streamlit app to the internet. The app is hosted on port 8501, and localtunnel provides a public URL through which the app can be accessed.

1: !streamlit run app.py & npx localtunnel --port 8501
  • & 是一個 Linux/Unix Shell 的符號,表示在後台運行該命令。在這裡,它將 streamlit run app.py 放到後台執行,使得後續的指令可以繼續在同一個終端中執行,而不需要等待這個 Streamlit 應用結束。
  • npx:npx 是 Node.js 的一個工具,用來執行 Node.js 的命令。
  • localtunnel:localtunnel 是一個開源工具,允許你將本地運行的服務通過臨時的公共 URL 發布到互聯網上。它經常用來在開發環境中分享本地服務,或者測試時讓遠程用戶訪問。
  • –port 8501:這裡指定 localtunnel 將本地的 8501 端口開放到網路上。因為 streamlit run app.py 預設運行在 8501 端口上,所以 localtunnel 將這個端口的服務映射到一個臨時的公共 URL。

1.5. 秀資料

學生成績

 1: import streamlit as st
 2: import pandas as pd
 3: 
 4: st.title('學生成績')
 5: 
 6: df = pd.DataFrame({
 7:     '國文': [98, 76, 100, 38, 40],
 8:     '數學': [80, 46, 80, 67, 66]
 9: })
10: df
11: 
12: # 畫圖
13: st.line_chart(df)

1.6. Sidebar

1.6.1. 測試一下

 1: import streamlit as st
 2: import pandas as pd
 3: 
 4: st.title('學生成績')
 5: st.write('lalala')
 6: # 數據
 7: df = pd.DataFrame({
 8:     '國文': [98, 76, 100, 38, 40],
 9:     '數學': [80, 46, 80, 67, 66]
10: })
11: 
12: st.sidebar.write('選項1')
13: st.sidebar.markdown('選項2')
14: with st.sidebar:
15:     st.write('選項3')
16: 
17: df

1.6.2. 練習

  • 請自行在sidebar和main area裡加入一些文字
  • 可以發現sidebar是可以接受markdown語法的,那麼,你能否應用markdown語法在sidebar裡放一個google的連結呢?

1.7. 選單

1.7.1. 連結式選單

 1: import streamlit as st
 2: import pandas as pd
 3: 
 4: st.title('學生成績')
 5: 
 6: # 數據
 7: df = pd.DataFrame({
 8:     '國文': [98, 76, 100, 38, 40],
 9:     '數學': [80, 46, 80, 67, 66]
10: })
11: 
12: # 側邊欄連結
13: st.sidebar.markdown("[查看數據](?page=table)")
14: st.sidebar.markdown("[畫圖](?page=chart)")
15: 
16: # 獲取當前URL參數
17: query_params = st.query_params
18: page = query_params.get("page", "table")
19: 
20: # 根據URL參數顯示相應的內容
21: if page == 'table':
22:     st.write('學生成績數據表')
23:     st.dataframe(df)
24: elif page == 'chart':
25:     st.write('學生成績折線圖')
26:     st.line_chart(df)

1.7.2. 下拉式選單

 1: import streamlit as st
 2: import pandas as pd
 3: import matplotlib.pyplot as plt
 4: 
 5: st.title('學生成績')
 6: 
 7: # 數據
 8: df = pd.DataFrame({
 9:     '國文': [98, 76, 100, 38, 40],
10:     '數學': [80, 46, 80, 67, 66]
11: })
12: 
13: # 側邊欄選擇
14: st.sidebar.write('選單')
15: option = st.sidebar.selectbox(
16:     '請選擇操作',
17:     ['查看成績', '畫折線圖']
18: )
19: 
20: # 根據選擇顯示相應的內容
21: if option == '查看成績':
22:     st.write('學生成績表')
23:     st.dataframe(df)
24: elif option == '畫折線圖':
25:     st.write('學生成績折線圖')
26:     fig, ax = plt.subplots()
27:     ax.plot(df['國文'])
28:     ax.plot(df['數學'])
29:     ax.set_xticks(range(5))
30:     ax.set_xticklabels(range(1, len(df) + 1))
31:     st.pyplot(fig)

1.7.3. 課堂練習

請參考Google Classroom中的[實作練習7]更專業的資料處理工具: Pandas,新增三種選單功能

  • 查看全班成績
  • 國文科成績長條圖
  • 各科Box圖
  • 請解決畫圖時中文出現亂碼的問題
  • 請善用ChatGPT

完成結果參考下圖:

2024-08-08_16-05-46_2024-08-08_15-09-45 (1).gif

1.8. 地圖

1.8.1. 單一地標

 1: import streamlit as st
 2: import pandas as pd
 3: 
 4: st.title('雲林智慧教育中心')
 5: 
 6: data = pd.DataFrame({
 7:     'lat': 23.67,
 8:     'lon': 120.39,
 9:     'name': ['雲林智慧教育中心']
10: })
11: 
12: st.map(data)

1.8.2. 兩個或以上地標

 1: import streamlit as st
 2: import pandas as pd
 3: 
 4: st.title('雲林')
 5: # 定義不同地點的數據
 6: locs = {
 7:     '雲林智慧教育中心': {'lat': 23.67, 'lon': 120.39},
 8:     '雲林高鐡站': {'lat': 23.738, 'lon': 120.428}
 9: }
10: 
11: data = pd.DataFrame([
12:     {'lat': locs['雲林智慧教育中心']['lat'], 'lon': locs['雲林智慧教育中心']['lon'], 'name': '雲林智慧教育中心'},
13:     {'lat': locs['雲林高鐡站']['lat'], 'lon': locs['雲林高鐡站']['lon'], 'name': '雲林高鐡站'}
14: ])
15: 
16: st.map(data)
17: 

1.8.3. 加入選單

 1: import streamlit as st
 2: import pandas as pd
 3: 
 4: st.title('雲林智慧教育中心')
 5: # 定義不同地點的數據
 6: locations = {
 7:     '雲林智慧教育中心': {'lat': 23.67, 'lon': 120.39},
 8:     '雲林高鐡站': {'lat': 23.738, 'lon': 120.428}
 9: }
10: 
11: # 在側邊欄中選擇地點
12: st.sidebar.write('選單')
13: option = st.sidebar.selectbox(
14:     '請選擇地點',
15:     ['雲林智慧教育中心', '雲林高鐡站'])
16: 
17: # 根據選擇的地點更新地圖數據
18: selected_location = locations[option]
19: data = pd.DataFrame({
20:     'lat': [selected_location['lat']],
21:     'lon': [selected_location['lon']],
22:     'name': [option]
23: })
24: selected_location['lat']
25: selected_location['lon']
26: option
27: 
28: st.map(data)

1.8.4. 課堂練習

  • 請加入你家的地圖
  • 請加入和你學校的地圖

#+begin_src php -r -n :results output :exports both

1.9. 照相

 1: import streamlit as st
 2: 
 3: # 取得由相機輸入的影像緩衝資料
 4: imgBuffer = st.camera_input("Take a picture")
 5: 
 6: if imgBuffer is not None:
 7:     # 將緩衝資料轉換為二進位資料
 8:     imgData = imgBuffer.getvalue()
 9: 
10:     with open("/Users/letranger/Desktop/captured_image.png", "wb") as f:
11:         f.write(imgData)
12: 
13:     st.success("影響成功儲存!")

1.10. Deploy you app

1.10.1. upload to github

1.10.2. streamlit.io

1.11. 研習用範例

1.11.1. 需要先在本機端安裝的套件

1: pip3 install pandas
2: pip3 install streamlit
3: pip3 install plotly
4: pip3 install scikit-learn

1.11.2. 範例程式

 1: import pandas as pd
 2: import streamlit as st
 3: import plotly.express as px
 4: from sklearn.cluster import KMeans
 5: 
 6: # 讀取資料
 7: test = pd.read_csv("https://letranger.github.io/working/scores.csv")
 8: 
 9: # Streamlit 應用程式標題
10: st.title("分數分佈")
11: 
12: # 設定側邊欄選單
13: st.sidebar.write('選單')
14: 
15: # 科目選擇下拉選單
16: option = st.sidebar.selectbox(
17:     '請選擇科目',
18:     ['國文', '英文', '數學', '物理']
19: )
20: 
21: # 顯示資料框
22: st.write("### 資料", test)
23: 
24: # 將分數依每10分分一組
25: test['binned'] = pd.cut(test[option], bins=range(0, 101, 10))
26: 
27: # 計算每個區間的頻率
28: frequency = test['binned'].value_counts().sort_index()
29: # 轉換為資料框格式,方便 Streamlit 顯示
30: frequency_df = pd.DataFrame({'分數區間': frequency.index.astype(str), '頻率': frequency.values})
31: 
32: # 使用 Streamlit 顯示長條圖
33: st.bar_chart(frequency_df.set_index('分數區間'))
34: 
35: # KMeans 聚類
36: # 使用滑桿選擇 k 值(聚類數量)
37: k = st.slider("選擇聚類的數量 k", 2, 10, 3)
38: kmeans = KMeans(n_clusters=k)  # 預設分為 k 群
39: kmeans.fit(test[['國文', '英文']])  # 使用 '國文' 和 '英文' 進行聚類
40: clusters = kmeans.predict(test[['國文', '英文']])
41: 
42: # 將聚類結果添加到資料框
43: test['聚類'] = clusters
44: 
45: # 使用 Plotly 繪製聚類結果的散點圖
46: fig2 = px.scatter(test, x='國文', y='英文', color='聚類', title='國文與英文分數的聚類結果')
47: st.plotly_chart(fig2)

1.12. 執行結果

你也可以把你開發好的程式透過Github發佈到Streamlit的免費雲端平台https://streamlit.io/像這樣

Streamlit-Demo.gif

Figure 2: Streamlit執行範例

2. Gradio

讓只有command line I/O的python程式搖身一變成為web service。

2.1. 安裝套件

1: pip3 install gradio

2.2. Hello world1

  • fn :被 UI 裝飾的函式
  • inputs :輸入元件。如 “text” 、 “image” 、 “audio” 等
  • outputs :輸出元件。如 “text” 、 “image” 、 “label” 等

Gradio 支援 20 多種不同的元件型別,其中大部分都可以作為輸入/輸出元件,詳見官網文件gradio Docs

1: import gradio as gr
2: 
3: def greet(name):
4:     return "Hello " + name + "!!"
5: 
6: demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7: 
8: demo.launch()

2024-03-07_16-09-49_2024-03-07_16-09-26.png

Figure 3: 執行畫面

2.3. 數字 I/O

 1: import gradio as gr
 2: 
 3: def BMI(h, w):
 4:   h /= 100
 5:   return f'BMI值: {w/(h*h)}'
 6: 
 7: ui = gr.Interface(
 8:     fn=BMI, inputs=[gr.Slider(100, 240, label="身高(cm)"), gr.Slider(40, 200, label="體重(kg)")],
 9:     outputs=["text"]
10: )
11: ui.launch(share=True)

2024-03-07_16-41-11_2024-03-07_16-40-52.png

Figure 4: 執行畫面

2.3.1. [課堂練習]三角形面積   TNFSH

輸入三角形三邊長(1..100),輸出面積、周長

2.4. 文字 I/O

 1: import gradio as gr
 2: 
 3: def greet(name):
 4:     return "Hello " + name + "!"
 5: 
 6: demo = gr.Interface(
 7:     fn=greet,
 8:     inputs=gr.Textbox(lines=2, placeholder="Name Here..."),
 9:     outputs="text",
10: )
11: demo.launch(share=True)

2024-03-07_16-44-41_2024-03-07_16-44-28.png

Figure 5: 執行畫面

2.5. 多資料 I/O

 1: import gradio as gr
 2: 
 3: def greet(name, is_morning, temperature):
 4:     salutation = "Good morning" if is_morning else "Good evening"
 5:     greeting = f"{salutation} {name}. It is {temperature} degrees today"
 6:     celsius = (temperature - 32) * 5 / 9
 7:     return greeting, round(celsius, 2)
 8: 
 9: demo = gr.Interface(
10:     fn=greet,
11:     inputs=["text", "checkbox", gr.Slider(0, 100)],
12:     outputs=["text", "number"],
13: )
14: demo.launch(share=True)

2024-03-07_16-46-19_2024-03-07_16-46-06.png

Figure 6: 執行畫面

2.6. 圖形 I/O

 1: import gradio as gr
 2: import matplotlib.pyplot as plt
 3: import numpy as np
 4: def curve(a, b, c):
 5:     x = np.arange(-3, 3, 0.3)
 6:     y = a*x**2 + b*x + c
 7:     fig = plt.figure()
 8:     plt.plot(x, y)
 9:     print(x)
10:     print(y)
11:     return fig
12: inputs = [gr.Slider(0, 10, 5), gr.Slider(0, 10, 5), gr.Slider(0, 10, 5)]
13: outputs = gr.Plot()
14: demo = gr.Interface(
15:     fn=curve,
16:     inputs=inputs,
17:     outputs=outputs,
18:     cache_examples=True,)
19: demo.launch(share=True)

2024-03-07_16-51-43_2024-03-07_16-51-32.png

Figure 7: 執行畫面

2.7. Button

 1: import gradio as gr
 2: 
 3: def greet(name):
 4:     return "Hello " + name + "!"
 5: 
 6: with gr.Blocks() as demo:
 7:     name = gr.Textbox(label="Name")
 8:     output = gr.Textbox(label="Output Box")
 9:     greet_btn = gr.Button("Greet")
10:     greet_btn.click(fn=greet, inputs=name, outputs=output)
11: 
12: demo.launch(share=True)

2024-03-11_20-11-32_2024-03-11_20-10-15.gif

Figure 8: 執行畫面

2.8. Radio

 1: import gradio as gr
 2: 
 3: def greet(gender, name):
 4:     if gender == "Male":
 5:         return "Hello, Mr. " + name + "!"
 6:     else:
 7:         return "Hello, Ms. " + name + "!"
 8: 
 9: with gr.Blocks() as demo:
10:     input = [gr.Radio(["Male", "Female"]), gr.Textbox(label="Name")]
11:     output = gr.Textbox(label="Output Box")
12:     greet_btn = gr.Button("Greet")
13:     greet_btn.click(fn=greet, inputs=input, outputs=output)
14: 
15: demo.launch(share=True)

2024-03-11_20-13-52_2024-03-11_20-13-00.gif

Figure 9: 執行畫面

2.9. Tab(分頁)

適合多功能的程式(靜態的多重輸入)

 1: import gradio as gr
 2: 
 3: def tri(a, b, c):
 4:     import math
 5:     # 使用海龍公式計算半周長
 6:     s = (a + b + c) / 2
 7:     # 使用半周長計算面積
 8:     area = math.sqrt(s * (s - a) * (s - b) * (s - c))
 9:     return round(area,2)
10: 
11: def rect(a, b):
12:     return round(a*b,2)
13: 
14: area1 = gr.Interface(
15:     tri,
16:     [gr.Slider(label="長"), gr.Slider(label="寬"), gr.Slider(label="高") ],
17:     gr.Number(label="面積"),
18: )
19: 
20: area2 = gr.Interface(
21:     rect,
22:     [ gr.Slider(label="長"), gr.Slider(label="寬") ],
23:     gr.Number(label="面積"),
24: )
25: 
26: gr.TabbedInterface(
27:     [area1, area2], ["三角形", "長方形"]
28: ).launch()

2024-04-16_16-05-40_gradio-tabs.gif

Figure 10: 分頁式的Gradio

3. Flask

3.1. Button

 1: from flask import Flask
 2: app = Flask(__name__)
 3: 
 4: @app.route("/")
 5: def hello():
 6:     title = "<title>Advanced Materials of Python</title>"
 7:     h1 = "<h1>Python based web</h1>"
 8:     p1 = "<p>這是用Python開發的網站</p>"
 9:     return title+h1+p1
10: 
11: if __name__ == "__main__":
12:     app.run()

FlashSite.jpg

Figure 11: Flask Web Site

3.2. Input form2

2024-03-11_21-44-56_2024-03-11_21-43-18.gif

Figure 12: 執行畫面

3.2.1. Python

 1: # Flask網站前後端互動 09 - 超連結與圖片
 2: # 載入Flask、Request、render_template
 3: from flask import Flask, request, render_template
 4: 
 5: app = Flask(__name__, template_folder='templates',
 6:             static_folder="public",
 7:             static_url_path="/")
 8: 
 9: # 處理路徑 / 的對應函市
10: @app.route("/")
11: 
12: def main():
13:     return render_template("index.html")
14: 
15: @app.route("/page")
16: 
17: def page():
18:     #從main.html頁面中讀取姓名,存在name中
19:     name = request.args.get("nameis")
20:     #將name的資料轉給pate.html中的變數namepage
21:     return render_template("page.html", namepage=name)
22: # 啟動Server
23: 
24: if __name__ == '__main__':
25:     app.debug = True
26:     app.run()

3.2.2. templates

  1. 建立public資料夾,放入一個head.png圖檔
  2. 建立templates資料夾
  3. 以下兩個html檔要放在templates資料夾中
3.2.2.1. index.html
 1: <!DOCTYPE html>
 2: <html lang="en">
 3: 
 4: <head>
 5:     <meta charset="UTF-8">
 6:     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 7:     <meta name="viewport" content="width=device-width, initial-scale=1.0">
 8:     <title>這是標題</title>
 9: </head>
10: 
11: <body>
12:     <h3>網頁的主畫面</h3>
13:     <form action="/page">
14:         名字:<input type="text" name="nameis">
15:         <button>點擊送出</button>
16:     </form>
17: </body>
18: 
19: </html>
3.2.2.2. page.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>page1</title>

</head>

<body>
    <h1>我的名字叫 {{namepage}}</h1>
</body>

</html>

4. tkinter

4.1. 安裝

4.1.1. MacOS

於PyCharm的terminal下輸入brew install python-tk@Python版本
如果系統的預設python版本為3.9,則輸入

1: brew install python-tk@3.9
2: pip install tk

4.2. DEMO #1

 1: # -*- coding: utf-8 -*-
 2: import tkinter as tk
 3: from tkinter import messagebox
 4: # 按完button要做什麼
 5: def test():
 6:     tk.messagebox.showinfo('測試', 'Hi')
 7: 
 8: # main window
 9: root = tk.Tk()
10: root.title('my window')
11: root.geometry('200x150')
12: 
13: root.configure(background='white')
14: 
15: myentry = tk.Entry(root)
16: myentry.pack()
17: 
18: # Button
19: myButton = tk.Button(root, text='Button', command=test)
20: myButton.pack()
21: 
22: # Label
23: resultLabel = tk.Label(root, text='這是Label')
24: resultLabel.pack()
25: 
26: root.mainloop()

2024-03-12_10-24-30_2024-03-12_10-24-05.png

Figure 13: 執行畫面

4.3. DEMO #2

 1: # -*- coding: utf-8 -*-
 2: import tkinter as tk
 3: from tkinter import messagebox
 4: 
 5: def button_event():
 6:     #print(var.get())
 7:     if var.get() == '':
 8:         tk.messagebox.showerror('message', '未輸入答案')
 9:     elif var.get() == '2':
10:         tk.messagebox.showinfo('message', '答對了!')
11:     else:
12:         tk.messagebox.showerror('message', '答錯')
13: 
14: root = tk.Tk()
15: root.title('my window')
16: 
17: # label
18: mylabel = tk.Label(root, text='1+1=')
19: mylabel.grid(row=0, column=0)
20: 
21: var = tk.StringVar()
22: myentry = tk.Entry(root, textvariable=var)
23: myentry.grid(row=0, column=1)
24: 
25: mybutton = tk.Button(root, text='完成', command=button_event)
26: mybutton.grid(row=1, column=1)
27: 
28: root.mainloop()

2024-03-12_10-27-00_2024-03-12_10-25-57.gif

Figure 14: 執行畫面

5. PyInstaller

5.1. 安裝pyinstaller

1: pip3 install pyinstaller

5.2. 準備要打包的檔案

5.2.1. 找一個喜歡的icon

此處我下載了一個icns,命名為imac.icns,與底下的403qq.py存於同一資料夾裡,如果你懶到不想自己找,也可以按這裡下載我的icns圖示檔

5.2.2. 以前述tkinter demo#2為例,將下列程式命名為403qq.py

 1: import tkinter as tk
 2: from tkinter import messagebox
 3: 
 4: def button_event():
 5:     #print(var.get())
 6:     if var.get() == '':
 7:         tk.messagebox.showerror('message', '未輸入答案')
 8:     elif var.get() == '2':
 9:         tk.messagebox.showinfo('message', '答對了!')
10:     else:
11:         tk.messagebox.showerror('message', '答錯')
12: 
13: root = tk.Tk()
14: root.title('my window')
15: 
16: # label
17: mylabel = tk.Label(root, text='1+1=')
18: mylabel.grid(row=0, column=0)
19: 
20: var = tk.StringVar()
21: myentry = tk.Entry(root, textvariable=var)
22: myentry.grid(row=0, column=1)
23: 
24: mybutton = tk.Button(root, text='完成', command=button_event)
25: mybutton.grid(row=1, column=1)
26: 
27: root.mainloop()

5.3. 打包

1: pyinstaller --icon imac.icns --noconsole -n 403QQ 403qq.py

成功執行後,會在同一資料夾中看到一個dist的資料夾,裡面有一支403QQ的應用程式,試著執行看看

2024-03-12_12-56-19_2024-03-12_12-55-49.png

Figure 15: 編譯後的應用程式: 403QQ

6. Flet

7. TODO Kivy

8. PyQt

1: pip3 install PyQt6
 1: import sys
 2: from PyQt6.QtWidgets import QApplication, QWidget
 3: from PyQt6.QtGui import QIcon
 4: 
 5: class Window(QWidget):
 6:     def __init__(self):
 7:         super().__init__()
 8:         self.setWindowTitle("PyQT")
 9:         self.setFixedHeight(200)
10:         self.setFixedWidth(200)
11:         self.setGeometry(500, 300, 400, 300)
12:         stylesheet = self.setStyleSheet('background-color:Gray')
13: 
14: app = QApplication([])
15: window = Window()
16: 
17: window.show()
18: sys.exit(app.exec())

9. Resources

Footnotes:

Author: Yung-Chin Yen

Created: 2024-09-26 Thu 22:35