顯示具有 pyqt 標籤的文章。 顯示所有文章
顯示具有 pyqt 標籤的文章。 顯示所有文章

2019年12月13日 星期五

#桌面上的計算機(三)--一些外觀上的修訂

  • 只是在顯示效果,計算機並不能執行,請自行加在適當的地方。
  • 必要的地方,使用「##」做了註解。
  • 說明不多,請直接看程式的註解。
(以下只是練習,只有外觀,無法操作。)
  • 原來的計算機外觀
每一個視窗左上角都會有一個小圖示。你也可以自己加。
  1. #加window icon

  2. import sys #只是為了使用在釋放程式的記憶體

  3. from PyQt5.QtWidgets import QApplication #qt的應用程式
  4. from PyQt5.QtWidgets import QLabel #qt的Label
  5. from PyQt5.QtWidgets import QWidget #qt的部件,就是我們要的視窗

  6. ##目錄中要有icon.png
  7. from PyQt5 import QtGui  ##為了加一個window icon

  8. app = QApplication(sys.argv) #建立主程式的實體 app ,參數是一個list,如果不需要sys.argv,可以改成[]
  9. #以下一一建立程式中的顯示部件
  10. window = QWidget() #建立視窗實體
  11. window.setWindowTitle('第一個視窗程式') #視窗的抬頭
  12. window.setGeometry(200, 200, 280, 80) #視窗的位置和大小(x,y,長,寬)
  13. #window.move(60, 15) #重新將視窗移到電腦螢幕的(60,15)位置
  14. helloMsg = QLabel('<h1>Hello World!</h1>', parent=window) #建立標籤實體
  15. helloMsg.move(60, 15) #標籤移到視窗中的某位置

  16. window.setWindowIcon(QtGui.QIcon('icon.png'))  ##這行將icon放上去。

  17. window.show() #將視窗設定為顯示
  18. sys.exit(app.exec()) #開始執行應用程式,並在結束後,釋放記憶體。如果是python2,要用app.exec_()。
  1. ##改變按鈕換字型和顏色

  2. import sys

  3. from PyQt5.QtWidgets import QApplication  #qt應用程式
  4. from PyQt5.QtWidgets import QMainWindow  #qt主視窗
  5. from PyQt5.QtWidgets import QWidget  #qt總部件
  6. from PyQt5 import QtGui  #為了加一個window icon,這裡可以省略。
  7. from PyQt5.QtCore import Qt  ##一般性質的設定
  8. from PyQt5.QtWidgets import QGridLayout  #格狀排列
  9. from PyQt5.QtWidgets import QLineEdit   #單行文字
  10. from PyQt5.QtWidgets import QPushButton  #按鈕
  11. from PyQt5.QtWidgets import QVBoxLayout  #垂直排列
  12. from functools import partial  #有關function的工作

  13. #這是原作者,感謝。
  14. __version__ = '0.1'
  15. __author__ = 'Leodanis Pozo Ramos'

  16. #定義主視窗,繼承自QMainWindow
  17. class PyCalcUi(QMainWindow):
  18.     #初始化,訂定視窗外觀
  19.     def __init__(self):
  20.         super().__init__()
  21.         self.setWindowTitle('py小計算機')
  22.         self.setFixedSize(235, 235) #固定大小,免得計算機變形。
  23.         self.generalLayout = QVBoxLayout() #整體的部件是垂直排列
  24.         # 建立中央部件
  25.         self._centralWidget = QWidget(self)  #先建立總部件實體(self相當於parent=self,top level的物件沒有parent了,所以不能省略。)
  26.         self.setCentralWidget(self._centralWidget)  #再設定成中央部件
  27.         self._centralWidget.setLayout(self.generalLayout)  #中央部件就設定為整體垂直排列
  28.         self._createDisplay() #計算機顯示數字的部件
  29.         self._createButtons() #計算機顯示按鈕的部件

  30.         #self.setWindowIcon(QtGui.QIcon('icon.png'))  #這行將icon放上去。這行可以省略。
  31.     
  32.     #計算機顯示數字的部件
  33.     def _createDisplay(self):
  34.         self.display = QLineEdit() #顯示只要一行
  35.         self.display.setFixedHeight(35)  #顯示幕的高度
  36.         self.display.setAlignment(Qt.AlignRight)  #靠右顯示
  37.         self.display.setReadOnly(True)  #設定唯讀
  38.         
  39.         self.generalLayout.addWidget(self.display) #將以上設定加入整體垂直設定中
  40.         
  41.     def _createButtons(self):
  42.         self.buttons = {}
  43.         buttonsLayout = QGridLayout()
  44.         #在字典中,設定按鈕顯示的數字和在格狀排列中的座標
  45.         buttons = {'7': (0, 0),
  46.                    '8': (0, 1),
  47.                    '9': (0, 2),
  48.                    '/': (0, 3),
  49.                    'C': (0, 4),
  50.                    '4': (1, 0),
  51.                    '5': (1, 1),
  52.                    '6': (1, 2),
  53.                    '*': (1, 3),
  54.                    '(': (1, 4),
  55.                    '1': (2, 0),
  56.                    '2': (2, 1),
  57.                    '3': (2, 2),
  58.                    '-': (2, 3),
  59.                    ')': (2, 4),
  60.                    '0': (3, 0),
  61.                    '00': (3, 1),
  62.                    '.': (3, 2),
  63.                    '+': (3, 3),
  64.                    '=': (3, 4),
  65.                   }
  66.         #取出字典中的文字和座標,一一擺進格狀排列中
  67.         for btnText, pos in buttons.items():
  68.             self.buttons[btnText] = QPushButton(btnText)  #設定按鈕實體,以及顯示的文字
  69.             ##設定字體
  70.             self.buttons[btnText].setStyleSheet('QPushButton {font: bold;font-size: 30px;}')
  71.             
  72.             ##set button color
  73.             if btnText in ['/','*','-','+','(',')']:
  74.                 self.buttons[btnText].setStyleSheet('QPushButton {background-color: #ff8028; color: white;font: bold;font-size: 30px;}')
  75.             elif btnText == '=':
  76.                 self.buttons[btnText].setStyleSheet('QPushButton {background-color: #01a2e8; color: white;font: bold;font-size: 30px;}')
  77.             elif btnText == 'C':
  78.                 self.buttons[btnText].setStyleSheet('QPushButton {background-color: #ed1d25; color: white;font: bold;font-size: 30px;}')
  79.             
  80.             
  81.             buttonsLayout.addWidget(self.buttons[btnText], pos[0], pos[1])  #擺進格狀排列
  82.             
  83.         self.generalLayout.addLayout(buttonsLayout)#將以上設定加入整體垂直設定中
  84.     def setDisplayText(self, text):
  85.         """Set display's text."""
  86.         self.display.setText(text)
  87.         self.display.setFocus()

  88.     def displayText(self):
  89.         """Get display's text."""
  90.         return self.display.text()

  91.     def clearDisplay(self):
  92.         """Clear the display."""
  93.         self.setDisplayText("")
  94. # 主程式
  95. def main():
  96.     pycalc = QApplication(sys.argv)  #建立app
  97.     view = PyCalcUi()  #建立主視窗實體
  98.     
  99.     view.show()  
  100.     sys.exit(pycalc.exec())

  101. if __name__ == '__main__':
  102.     main()

  • 練習加中文的+-÷×,看起來比較大方。  pycalc-r3.py
  1. ##換一下+-÷×符號,看起來比較大方。
  2. ##小心,這裡只是顯示用,後續要放到計算式裡面的時候,必需轉換回來/*,這樣eval()才能正確計算。

  3. import sys

  4. from PyQt5.QtWidgets import QApplication  #qt應用程式
  5. from PyQt5.QtWidgets import QMainWindow  #qt主視窗
  6. from PyQt5.QtWidgets import QWidget  #qt總部件
  7. from PyQt5 import QtGui  #為了加一個window icon,這裡可以省略。
  8. from PyQt5.QtCore import Qt  #一般性質的設定
  9. from PyQt5.QtWidgets import QGridLayout  #格狀排列
  10. from PyQt5.QtWidgets import QLineEdit   #單行文字
  11. from PyQt5.QtWidgets import QPushButton  #按鈕
  12. from PyQt5.QtWidgets import QVBoxLayout  #垂直排列
  13. from functools import partial  #有關function的工作

  14. #這是原作者,感謝。
  15. __version__ = '0.1'
  16. __author__ = 'Leodanis Pozo Ramos'

  17. #定義主視窗,繼承自QMainWindow
  18. class PyCalcUi(QMainWindow):
  19.     #初始化,訂定視窗外觀
  20.     def __init__(self):
  21.         super().__init__()
  22.         self.setWindowTitle('py小計算機')
  23.         self.setFixedSize(235, 235) #固定大小,免得計算機變形。
  24.         self.generalLayout = QVBoxLayout() #整體的部件是垂直排列
  25.         # 建立中央部件
  26.         self._centralWidget = QWidget(self)  #先建立總部件實體(self相當於parent=self,top level的物件沒有parent了,所以不能省略。)
  27.         self.setCentralWidget(self._centralWidget)  #再設定成中央部件
  28.         self._centralWidget.setLayout(self.generalLayout)  #中央部件就設定為整體垂直排列
  29.         self._createDisplay() #計算機顯示數字的部件
  30.         self._createButtons() #計算機顯示按鈕的部件

  31.         #self.setWindowIcon(QtGui.QIcon('icon.png'))  #這行將icon放上去。這行可以省略。
  32.     
  33.     #計算機顯示數字的部件
  34.     def _createDisplay(self):
  35.         self.display = QLineEdit() #顯示只要一行
  36.         self.display.setFixedHeight(35)  #顯示幕的高度
  37.         self.display.setAlignment(Qt.AlignRight)  #靠右顯示
  38.         self.display.setReadOnly(True)  #設定唯讀
  39.         
  40.         self.generalLayout.addWidget(self.display) #將以上設定加入整體垂直設定中
  41.         
  42.     def _createButtons(self):
  43.         self.buttons = {}
  44.         buttonsLayout = QGridLayout()
  45.         #在字典中,設定按鈕顯示的數字和在格狀排列中的座標
  46.         buttons = {'7': (0, 0),
  47.                    '8': (0, 1),
  48.                    '9': (0, 2),
  49.                    '÷': (0, 3), ##÷
  50.                    'C': (0, 4),
  51.                    '4': (1, 0),
  52.                    '5': (1, 1),
  53.                    '6': (1, 2),
  54.                    '×': (1, 3), ##×
  55.                    '(': (1, 4),
  56.                    '1': (2, 0),
  57.                    '2': (2, 1),
  58.                    '3': (2, 2),
  59.                    '-': (2, 3),##-
  60.                    ')': (2, 4),
  61.                    '0': (3, 0),
  62.                    '00': (3, 1),
  63.                    '.': (3, 2),
  64.                    '+': (3, 3),##+
  65.                    '=': (3, 4),
  66.                   }
  67.         #取出字典中的文字和座標,一一擺進格狀排列中
  68.         for btnText, pos in buttons.items():
  69.             self.buttons[btnText] = QPushButton(btnText)  #設定按鈕實體,以及顯示的文字
  70.             #設定字體
  71.             self.buttons[btnText].setStyleSheet('QPushButton {font: bold;font-size: 30px;}')
  72.             
  73.             #set button color
  74.             if btnText in ['+','-','×','÷','(',')']:##這裡也改變了
  75.                 self.buttons[btnText].setStyleSheet('QPushButton {background-color: #ff8028; color: white;font: bold;font-size: 30px;}')
  76.             elif btnText == '=':
  77.                 self.buttons[btnText].setStyleSheet('QPushButton {background-color: #01a2e8; color: white;font: bold;font-size: 30px;}')
  78.             elif btnText == 'C':
  79.                 self.buttons[btnText].setStyleSheet('QPushButton {background-color: #ed1d25; color: white;font: bold;font-size: 30px;}')
  80.             
  81.             
  82.             buttonsLayout.addWidget(self.buttons[btnText], pos[0], pos[1])  #擺進格狀排列
  83.             
  84.         self.generalLayout.addLayout(buttonsLayout)#將以上設定加入整體垂直設定中
  85.     def setDisplayText(self, text):
  86.         """Set display's text."""
  87.         self.display.setText(text)
  88.         self.display.setFocus()

  89.     def displayText(self):
  90.         """Get display's text."""
  91.         return self.display.text()

  92.     def clearDisplay(self):
  93.         """Clear the display."""
  94.         self.setDisplayText("")
  95. # 主程式
  96. def main():
  97.     pycalc = QApplication(sys.argv)  #建立app
  98.     view = PyCalcUi()  #建立主視窗實體
  99.     
  100.     view.show()  
  101.     sys.exit(pycalc.exec())

  102. if __name__ == '__main__':
  103.     main()
p.s.
在def _buildExpression(self, sub_exp): 中,還必須把符號換回英數,才能正確執行。

2019年12月10日 星期二

#桌面上的計算機(一)--基礎認識

--使用PyQt套件

#原文出處

#摘要紀錄與說明
--python的GUI套件,有 Tkinter, wxPython, PyQt, PySide2...等等
--PyQt5 是基於Qt5而來

--請直接下載檔案執行。如果是複製網頁上的程式,貼上後請注意縮排問題。
--程式碼的說明,就在程式裡。

#測試小部件
  • 建立虛擬環境    python -m venv myenv
  • 安裝    pip install pyqt5
#第一個視窗hello world(ex1.py)
      1. import sys #只是為了使用在釋放程式的記憶體


      2. from PyQt5.QtWidgets import QApplication #qt的應用程式
      3. from PyQt5.QtWidgets import QLabel #qt的Label
      4. from PyQt5.QtWidgets import QWidget #qt的總部件,就是這個程式的視窗

      5. app = QApplication(sys.argv) #建立主程式的實體 app ,參數是一個list,如果不需要sys.argv,可以改成[]

      6. #以下一一建立程式中的顯示部件
      7. window = QWidget() #建立視窗實體
      8. window.setWindowTitle('PyQt5 App') #視窗的抬頭
      9. window.setGeometry(200, 200, 280, 80) #視窗的位置和大小(x,y,長,寬)
      10. #window.move(60, 15) #重新將視窗移到電腦螢幕的(60,15)位置
      11. helloMsg = QLabel('<h1>Hello World!</h1>', parent=window) #建立標籤實體,qt5接受html標籤
      12. helloMsg.move(60, 15) #標籤移到視窗中的某位置

      13. window.show() #將視窗設定為顯示


      14. sys.exit(app.exec()) #開始執行應用程式,並在結束後,釋放記憶體。如果是python2,要用app.exec_()。
p.s.載入要花一點時間,結果視窗關閉後,才能再回到命令列視窗。

#建立基本概念
  1. Widgets:各種部件
  2. Layout managers:排列部件的方式
  3. Dialogs:對話視窗
  4. Main windows:主視窗
  5. Applications:程式
  6. Event loops:監聽事件
  7. Signals and slots:事件發出的訊號(signals)和對應的處理程式(slots)。
1. 各種部件
  • Buttons:按鈕
  • Labels:多行文字
  • Line edits:單行文字
  • Combo boxes:下拉列表
  • Radio buttons:單選按鈕
......

2. 排列部件方式
  1. QHBoxLayout:水平排列容器 ex2.py
  2. QVBoxLayout:垂直排列容器 ex3.py
  3. QGridLayout:格狀排列容器 ex4.py

  4. QFormLayout:表單形式容器 ex5.py
3. 對話視窗(和主視窗彼此獨立,可以想成就是一般軟體裡跳出來,讓我們設定內容的視窗)--初學應該先學主視窗
特性:
對話視窗有2個內定的按鈕,「ok」、「cancel」。
有model 和 modeless 二種,model要用建class。
model 要用.exec()呼叫,modeless則是用.show()

這裡的範例是使用model的對話視窗 ex6.py
4. 主視窗  ex7.py
特性:
內定有功能列、工具列、狀態列等等的排列部件
一定要有中央部件,才有內容嘛
可以開出對話視窗來完成特定功能
5. 程式
在這裡,運用的是MVC架構,程式就是Control。它從view監聽接收資料,轉到model去,model做好資料的運算,再藉由Control,送到view顯示。

6. 監聽事件
一個無限的迴圈,時時看看有沒有哪個部件發出訊號了。就是.exec()的運作。
註:python2 使用.exec_(),python3 使用.exec()和.exec_()都可以。(因為python2自己內部有.exec())

7. 事件發出的訊號和對應的處理程式  ex8.py
訊號,如滑鼠按鍵或鍵盤被按下等等,代表某一個部件狀態改變了,需要處理程式來做出必要的處置。
它們之間的機制有
一個訊號,發給一個或多個處理程式。
一個訊號,連結到另外一個訊號。
一個處理程式,處理多個訊號。

python程式寫法,widget.signal.connect(slot_function)
ex7.py 中的程式,btn.clicked.connect(greeting) 當按鈕按下去(click),就執行greeting程式。
程式需要傳遞參數時,
在程式定義的部份,如同一般函數,將參數寫在(  )內,使用在字串之內時,用{  }。
在程式呼叫的部份,要使用functools.partial來間接呼叫。btn.clicked.connect(functools.partial(greeting,"world"))
p.s.使用functools,要先import functools。
請見 ex9.py