添加、刪除、修改和編輯「事件」,托盤圖標,windows全局快捷鍵(已實現)前端
鬧鐘提醒功能 (未實現)python
對於「事件」的保存 (關機重啓以後仍然能夠顯示以前的未完成「事件」)(未實現)git
桌面浮動提醒,界面的動畫交互 ... 等 (未實現)github
對於這些功能,也不是要單單的實現這些功能,咱們能夠經過一些手段讓這些普通的功能更加受用戶的喜好,好比說:鬧鐘提示:你能夠添加一個貼心的小功能進去,當是、用戶使用電腦時間太久,便籤自動進行一些人性化的提醒之類。(這只是功能發散的一個方向)windows
widget.py
: 程序運行入口,主界面的實現https://github.com/zjuysw/memo.git
設計模式
>若是沒有使用過軟件,可能對下面的代碼註釋會有點不理解架構
主界面設置背景圖片: 採用QPalette。注:使用stylesheet會讓子widget繼承。(widget.py)app
<!-- lang: python -->ide
backImg = QPixmap('./img/1.png').scaled(self.size()) palette = QPalette() palette.setBrush(self.backgroundRole(), QBrush(backImg)) self.setPalette(palette)
圖標的背景圖片和樣式:採用stylesheet函數
特效(透明):採用QGraphicsOpacityEffect (mylable.py)
<!-- lang: python -->
self.opacity = QGraphicsOpacityEffect() self.opacity.setOpacity(0.7) self.setGraphicsEffect(self.opacity)
主要是重寫widget的鼠標事件 (mylable.py)
<!-- lang: python -->
def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.dragPos = event.globalPos() - self.pos() event.accept() def mouseMoveEvent(self, QMouseEvent): pw = self.parentWidget() # 獲取父widget,也就是本程序中的主widget widget1 = pw.getTrashRect() # 獲取主widget 的 垃圾箱widget(函數名沒有改過來) flag = self.isCollide(widget1, self) # 檢測兩個widget的碰撞 if flag: self.emit(SIGNAL('collideTrash'), True) # 碰撞就發射collideTrash信號 else: self.emit(SIGNAL('collideTrash'), False) # 如下代碼用於進行widget的拖拽 if QMouseEvent.buttons() == Qt.LeftButton: self.move(QMouseEvent.globalPos() - self.dragPos) QMouseEvent.accept() if QMouseEvent.buttons() == Qt.RightButton: QMouseEvent.ignore() def mouseReleaseEvent(self, QMouseEvent): # 拖拽動做完成以後檢測是否碰撞以肯定該widget是否被刪除 pw = self.parentWidget() widget1 = pw.getTrashRect() flag = self.isCollide(widget1, self) if flag: print "yes" self.emit(SIGNAL('collideTrash'), False) self.hide() self.destroy() else: self.emit(SIGNAL('collideTrash'), False) self.hide() self.show()
<!-- lang: python -->
parentWidget = QWidget() subWidget = QWidget(parentWidget) subWidget.emit(SIGNAL("sub")) parentWidget.connect(subWidget, SIGNAL("sub"), parentWidget.doSomething)
思路:一個layout中包含兩個layout,其中layout各自包含2個widget,分別是:內容lable,時間lable,編輯框textedit和肯定按鈕button。要顯示的時候,咱們讓編輯框和按鈕隱藏,編輯的時候,咱們讓內容和時間隱藏。(mylable.py)
<!-- lang: python -->
def mouseDoubleClickEvent(self, event): if event.button() == Qt.LeftButton: self.label.hide() self.timeLabel.hide() self.textEdit.show() self.textEdit.setFocus() self.textEdit.setText(self.label.text()) self.okBtn.show()
思路:假設垃圾桶爲widget1,咱們的顯示lable是widget2,因爲剛開始的時候垃圾桶在顯示lable的左下角,因此他們若是碰撞(重疊)就必然會有:widget2的右上角在widget1的左下角的右上方,widget2的左下角一定在widget1的右上角的左下方
<!-- lang: python -->
def isCollide(self, widget1, widget2): dict1 = {} dict1['size'] = widget1.size() dict1['pos'] = widget1.pos() dict2 = {} dict2['size'] = widget2.size() dict2['pos'] = widget2.pos() r1TopRightX = dict1['pos'].x() + dict1['size'].width() r1TopRightY = dict1['pos'].y() r1BottomLeftX = dict1['pos'].x() r1BottomLeftY = dict1['pos'].y() + dict1['size'].height() r2TopRightX = dict2['pos'].x() + dict2['size'].width() r2TopRightY = dict2['pos'].y() r2BottomLeftX = dict2['pos'].x() r2BottomLeftY = dict2['pos'].y() + dict2['size'].height() if r1TopRightX > r2BottomLeftX and r1TopRightY < r2BottomLeftY \ and r2TopRightX > r1BottomLeftX and r2TopRightY < r1BottomLeftY: return True else: return False
直接運用QTextEdit的QFocusEvent (mylable.py)
<!-- lang: python -->
def focusInEvent(self, event): print "edit" self.emit(SIGNAL("Editing")) def focusOutEvent(self, event): if event.reason() == 4: # popup focus event.ignore() else: self.emit(SIGNAL("EditFinish"))
使用python的ctypes模塊(Qt自己沒有相應全局快捷鍵處理類)(hotkey.py)
<!-- lang: python -->
#!/usr/bin/env python # -*- coding: utf8-*- import sys import time from ctypes import * from ctypes.wintypes import * from PyQt4.QtGui import QApplication import widget delta = 0.3 lastTime = 0 WM_HOTKEY = 0x0312 MOD_ALT = 0x0001 MOD_CONTROL = 0x0002 MOD_SHIFT = 0x0004 WM_KEYUP = 0x0101 class MSG(Structure): _fields_ = [('hwnd', c_int), ('message', c_uint), ('wParam', c_int), ('lParam', c_int), ('time', c_int), ('pt', POINT)] key = 192 # ~ key hotkeyId = 1 if not windll.user32.RegisterHotKey(None, hotkeyId, None, key): sys.exit("Cant Register Hotkey") msg = MSG() app = QApplication(sys.argv) w = widget.mainUi() while True: if (windll.user32.GetMessageA(byref(msg), None, 0, 0) != 0): if msg.message == WM_HOTKEY and msg.wParam == hotkeyId: if (time.time() - lastTime) < delta: w.show() else: pass lastTime = time.time() if msg.message == WM_KEYUP: print "up" w.myHide() windll.user32.TranslateMessage(byref(msg)) windll.user32.DispatchMessageA(byref(msg))
基本上看看PyQt的文檔差很少了(trayicon.py)
<!-- lang: python --> # -*- coding:utf8 -*- import sys from PyQt4 import QtCore, QtGui from PyQt4.QtCore import * from PyQt4.QtGui import * class TrayIcon(QSystemTrayIcon): def __init__(self, parent=None): super(TrayIcon, self).__init__(parent) self.initObjects() self.setObjects() self.activated.connect(self.iconClicked) def initObjects(self): self.menu = QMenu() self.quitAction = QAction(u"退出", self, triggered=self.exitApp) self.icon = QIcon('./img/icon.png') def setObjects(self): self.menu.addAction(self.quitAction) self.setIcon(self.icon) self.setContextMenu(self.menu) def iconClicked(self, reason): print reason if reason==2 or reason==3: pw = self.parent() if pw.isVisible(): pw.hide() else: pw.show() def exitApp(self): self.setVisible(False) qApp.quit() sys.exit() if __name__ == "__main__": import sys app = QApplication(sys.argv) ti = TrayIcon() ti.show() sys.exit(app.exec_())
好像本身編寫的過程當中遇到的比較難的技術問題就這些,不過關鍵仍是要把PyQt的一些基礎知識學牢固,本身組織軟件的時候把需求想清楚,把軟件的結構理清楚。歡迎_交流_與_指正_或者_提出更好的方法和建議_。思惟的碰撞總會有意想不到的驚喜
怎樣在代碼行數增多時,仍然保持它的可讀性和可維護性
。