PyQt Signal

  1. QObject:
    void destroyed ( QObject * obj = 0 )
    1. QWidget:
      void customContextMenuRequested ( const QPoint & pos )
      1. QGroupBox:
        void clicked ( bool checked = false )
        void toggled ( bool on )
      2. QAbstractButton:
        void clicked ( bool checked = false )
        void pressed ()
        void released ()
        void toggled ( bool checked )
        1. QRadioButton
        2. QPushButton
        3. QCheckBox:
          stateChanged ( int state )
        4. QToolButton:
          void triggered ( QAction * action )
      3. QDialog:
        void accepted ()
        void finished ( int result )
        void rejected ()
        1. QMessagebox:
          void buttonClicked ( QAbstractButton * button )
        2. QFileDialog:
          void currentChanged ( const QString & path )
          void directoryEntered ( const QString & directory )
          void fileSelected ( const QString & file )
          void filesSelected ( const QStringList & selected )
          void filterSelected ( const QString & filter )
        3. QProgressDialog:
          void canceled ()
        4. QColorDialog:
          void colorSelected ( const QColor & color )
          void currentColorChanged ( const QColor & color )
        5. QFontDialog:
          void currentFontChanged ( const QFont & font )
          void fontSelected ( const QFont & font )
      4. QComboBox:
        void activated ( int index )
        void activated ( const QString & text )
        void currentIndexChanged ( int index )
        void currentIndexChanged ( const QString & text )
        void editTextChanged ( const QString & text )
        void highlighted ( int index )
        void highlighted ( const QString & text )
        1. QFontComboBox:
          void currentFontChanged ( const QFont & font )
      5. QAbstractSpinBox:
        void editingFinished ()
        1. QSpinBox:
          void valueChanged ( int i )
          void valueChanged ( const QString & text )
        2. QDoubleSpinBox:
          void valueChanged ( double d )
          void valueChanged ( const QString & text )
        3. QDateTimeEdit:
          void dateChanged ( const QDate & date )
          void dateTimeChanged ( const QDateTime & datetime )
          void timeChanged ( const QTime & time )
      6. QDialogButtonBox:
        void accepted ()
        void clicked ( QAbstractButton * button )
        void helpRequested ()
        void rejected ()
      7. QLineEdit:
        void cursorPositionChanged ( int old, int new )
        void editingFinished ()
        void returnPressed ()
        void selectionChanged ()
        void textChanged ( const QString & text )
        void textEdited ( const QString & text )
      8. QMenu:
        void aboutToHide ()
        void aboutToShow ()
        void hovered ( QAction * action )
        void triggered ( QAction * action )
      9. QProgressBar:
        void valueChanged ( int value )
      10. QAbstractSlider:
        void actionTriggered ( int action )
        void rangeChanged ( int min, int max )
        void sliderMoved ( int value )
        void sliderPressed ()
        void sliderReleased ()
        void valueChanged ( int value )
        1. QSlider:
          valueChanged()
          sliderPressed()
          sliderMoved()
          sliderReleased()
        2. QDial
      11. QFrame
        1. QSplitter:
          void splitterMoved ( int pos, int index )
        2. QAbstractScrollArea
          1. QScrollArea
          2. QPlainTextEdit:
            void blockCountChanged ( int newBlockCount )
            void copyAvailable ( bool yes )
            void cursorPositionChanged ()
            void modificationChanged ( bool changed )
            void redoAvailable ( bool available )
            void selectionChanged ()
            void textChanged ()
            void undoAvailable ( bool available )
            void updateRequest ( const QRect & rect, int dy )
          3. QLabel:
            void linkActivated ( const QString & link )
            void linkHovered ( const QString & link )
      12. QStatusBar:
        void messageChanged ( const QString & message )
      13. QTabBar:
        void currentChanged ( int index )
        void tabCloseRequested ( int index )
        void tabMoved ( int from, int to )
      14. QTextEdit:
        void copyAvailable ( bool yes )
        void currentCharFormatChanged ( const QTextCharFormat & f )
        void cursorPositionChanged ()
        void redoAvailable ( bool available )
        void selectionChanged ()
        void textChanged ()
        void undoAvailable ( bool available )
        1. QTextBlowser:
          void anchorClicked ( const QUrl & link )
          void backwardAvailable ( bool available )
          void forwardAvailable ( bool available )
          void highlighted ( const QUrl & link )
          void highlighted ( const QString & link )
          void historyChanged ()
          void sourceChanged ( const QUrl & src )

PyQt Event サンプル

#encoding:utf-8
import sys
from PyQt4 import QtGui

class Example(QtGui.QWidget):
    def __init__(self, parent=None):
        super(Example, self).__init__(parent)
        self.setAcceptDrops(True)
        self.resize(150, 150)
        self.setWindowTitle("D&D")
        lineEdit(self)
        self.show()
    def dragEnterEvent(self, e):
        if e.mimeData().hasUrls():
            e.accept()
        else:
            e.ignore()
    def dropEvent(self, e):
        print("\n".join(u.toLocalFile() for u in e.mimeData().urls()))
    def moveEvent(self,e):
        print("move="+str(e.oldPos().x())
            +"_"+str(e.oldPos().y())
            +":"+str(e.pos().x())
            +"_"+str(e.pos().y()))
    def resizeEvent(self,e):
        print("resize="+str(e.oldSize().height())
            +"_"+str(e.oldSize().width())
            +":"+str(e.size().height())
            +"_"+str(e.size().width()))

    def showEvent(self,e):
        print("show:"+str(e.spontaneous()))
    def wheelEvent(self,e):
        print("wheel="+str(e.delta()/8)
            +"_"+str(e.orientation())
            +":"+str(e.x())
            +"_"+str(e.y()))
    def mouseMoveEvent(self,e):
        print("mouseMove="+bin(int(e.buttons())))


class lineEdit(QtGui.QLineEdit):
    def __init__(self, parent=None):
        super(lineEdit, self).__init__(parent)
        self.move(30,30)
    def keyPressEvent(self,e):
        super(lineEdit,self).keyPressEvent(e)
        print("text="+e.text()
            +",count="+str(e.count()))
            +",key="+hex(e.key())
            +",Modifiers="+hex(int(e.modifiers()))
            +",nativeVK="+str(e.nativeVirtualKey())
            +",nativeScanCode="+str(e.nativeScanCode())
            +",nativeModifiers="+bin(e.nativeModifiers())
            +",isAutoRepeat="+str(e.isAutoRepeat())
            +",matches="
                +str(e.matches(QtGui.QKeySequence.Copy))

def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
if __name__ == '__main__':
    main()

dragEnterEvent (QDragEnterEvent)

ドラッグしているマウスがこのウィジットに入ってきた時動く。
このイベントが無視されるときdragMoveEventも受け取らない。
eの中は

QPoint e.mimeData()
QMimeData e.pos()
Qt.MouseButtons e.mouseButtons()
Qt.KeyboardModifiers e.keyboardModifiers()

dragLeaveEvent (QDragLeaveEvent)

ドラッグして一旦ウィジットに入ったものがそのままドロップされず領域外でドロップされた時呼ばれる

dragMoveEvent (QDragMoveEvent)

ドラッグした状態でこのウィジットの上でマウスが動いているとき呼ばれる。eの中はだいたいdragEnterEventと同じ

dropEvent (QDropEvent)

名前の通り。eの中はdragEnterEventに
QWidget e.sourceが追加されたくらい。これはドラッグ元がこのアプリケーションの場合そのドラッグ元のウィジット自体を返すみたい。

enterEvent (QEvent)

マウスカーソルがウィジット内に入った時に呼ばれる

leaveEvent (QEvent)

マウスカーソルがウィジットを離れた時に呼ばれる

mouseMoveEvent mouseDoubleClickEvent mouseReleaseEvent mousePressEvent (QMouseEvent)

マウストラッキングのスイッチがオフの場合いずれかのマウスボタンが押されている場合しかmouseMoveEventは発生しないマウストラッキングがオンになっているとボタンが押されていなくてもイベントが発生する。
マウスを動かしている間にツールチップを追随させるにははじめにマウストラッキングを許可する。setToolTip()ではなくQToolTip.showText()を呼ぶとより確かに追随できる。

Qt.MouseButton e.button()
イベントを引き起こしたボタンを返す。mouseMoveEventにはいつもQt.NoButtonを返す
Qt.MouseButtons e.buttons()
イベントが呼ばれた時のボタンの状態を返す。参考:Qt.MouseButton
QPoint e.globalPos()
非同期性のウィンドウシステム(X11のような)では現在のマウスの位置(QCursor.pos())とイベント発生した位置が違ってしまうため必要とか何とか
int e.globalX()
int e.globalY()
bool e.hasExtendedInfo()
QPoint e.pos()
ハンドシェイクしたときは反応が追いつかないかもしれないけどそれはQtの所為ではなくウィンドウシステムに由来するもの。
int e.x()
int e.y()
QPOintF e.posF()

closeEvent (QCloseEvent)

ウィンドウを閉じるとき呼ばれる。

moveEvent (QMoveEvent)

ウィジットが(例えばウィンドウを動かしたりして)動き、移動し終わった時に呼ばれる。座標は動き始めと動き終わりしかわからない。

QPoint e.pos()
QPoint e.oldPos()

resizeEvent (QResizeEvent)

ウィジットがリサイズし、そしてし終わった時に呼ばれる。

Qsize e.oldSize()
Qsize e.size()

showEvent (QShowEvent)

self.show()した時呼ばれる。あと最小化して仕舞ってあったウィンドウを復元した時も呼ばれる。どちらなのかはe.spontaneous()で分かる

hideEvent (QHideEvent)

self.hide()した時以下ほぼ同文

childEvent (QChildEvent)

wheelEvent (QWheelEvent)

int e.delta()
ホイールの回された変化量を返す。度数法で表す場合8で割る。大抵のマウス(所謂ぬるぬるホイールではない物)は15度ずつ回る(らしい)ので、ひとつのステップはe.delta()/90で表される。
QPoint e.globalPos()
int e.globalX()
int e.globalY()
非同期性のウィンドウシステム(X11のような)では現在のマウスの位置(QCursor.pos())とイベント発生した位置が違ってしまうため必要とか何とか
Qt.Orientation e.orientation()
ホイールの回る向き(上下か左右か)
QPoint e.pos()
int e.x()
int e.y()

focusOutEvent

focusInEvent

keyPressEvent (QKeyEvent) keyReleaseEvent (QKeyEvent)

前提として当然ウィジットへのフォーカスが許可されていなければならない。(でないと文字入力ができない)

Qt.KeyboardModifiers e.modifiers()
必ずしもこの関数は正しくはない。(2つのShiftキーを押し、片方だけ離すなど)混乱させることが出来る
int e.count()
int e.key()
押されたキーのコード(Qt.Key参照)を返す。この関数は大文字と小文字を区別しない。そういう場合はe.text()を使う
int e.nativeModifiers()
int e.nativeScanCode()
MacではCarbon,Cocoaからはスキャンコードを取れないので使えない。(いつも1か0が返ってくる)
int e.nativeVirtualKey()
QString e.text()
実際に入力される文字を返す。Modifierキーが押されていると表示されなかったりする。その場合でもe.key()はちゃんと値を含んでいる
bool e.matches(QKeySequence.StandardKey key)
文字列のコピーなどの指定の操作があった場合Trueを返す
bool e.isAutoRepeat()
名前通り

PyQt QTreeWidget サンプル

#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore,Qt

class Example(QtGui.QWidget):
    def __init__(self):
        super(Example, self).__init__()
        self.initUI()
    def initUI(self):
        treeWidget = QtGui.QTreeWidget(self)
        treeWidget.setColumnCount(5)
        treeWidget.addTopLevelItem(QtGui.QTreeWidgetItem(["test2","あいうえお"]))
        item1 = QtGui.QTreeWidgetItem(treeWidget)
        item1.setText(0,"アイテム1")
        item1.setText(1,"abcde")
        item1_1 = QtGui.QTreeWidgetItem(["child","100"])
        item1.addChild(item1_1)
        treeWidget.setHeaderLabels(["ファイル名","パス","更新日時","拡張子"])
        treeWidget.move(10, 10)
        self.move(300, 300)
        self.setWindowTitle('Main window')
        treeWidget.scrollToItem(item1_1)#量が多い時自動でスクロールして一番上にitem1_1を表示する
        treeWidget.setCurrentItem(item1)#起動時にitem1が選択された状態になる
        print(treeWidget.headerItem().text(0))
        print(treeWidget.columnCount())
        print(treeWidget.currentColumn())
        print(treeWidget.currentItem().text(1))
        print(treeWidget.indexFromItem(item1).row())
        print(item1.childCount())
        print(item1.child(0).text(0))
        #item1.removeChild(item1_1) #item1_1が消える
        treeWidget.editItem(item1)
        treeWidget.addTopLevelItem(item1.clone())
        treeWidget.addTopLevelItem(item1)#意味がない
        item1.setText(0,"変更後")
        print(item1_1.parent().text(0))
        self.show()
def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

PyQtタイマーサンプル(他人のもの)

キュートなタイマー - None is None is Noneを勝手にPython3に直しただけ

#encoding:utf-8
from __future__ import division
from itertools import *
import sys
import time
import math

from PyQt4.QtGui import *
from PyQt4.QtCore import *

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

class TimerThread(QThread):
    def __init__(self, parent, length, interval=0.1):
        QThread.__init__(self, parent)
        self.length = length
        self._stop = False
        self.interval = interval
    def stop(self):
        self._stop = True
    def run(self):
        starttime = time.time()
        while not self._stop:
            remain = int(math.ceil(self.length - (time.time() - starttime)))
            self.emit(SIGNAL('tick(int)'), remain)
            if remain == 0:
                self.emit(SIGNAL('finish()'))
                break
            time.sleep(self.interval)

def setTabOrders(*widgets):
    for w1, w2 in pairwise(widgets):
        QWidget.setTabOrder(w1, w2)
class TimerWindow(QWidget):
    def __init__(self, parent=None):
        super(TimerWindow, self).__init__(parent)
        font = self.font()
        font.setPointSize(18)
        self.setFont(font)
        self.min = QLineEdit(self)
        self.min.setValidator(QIntValidator(self))
        self.sec = QLineEdit(self)
        self.sec.setValidator(QIntValidator(self))
        self.btn = QPushButton("Start", self)
        self.btn.setDefault(True)
        toplayout = QHBoxLayout()
        toplayout.addWidget(self.min)
        toplayout.addWidget(QLabel("分"))
        toplayout.addWidget(self.sec)
        toplayout.addWidget(QLabel("秒"))
        bottomlayout = QHBoxLayout()
        bottomlayout.addWidget(self.btn)
        layout = QVBoxLayout()
        layout.addLayout(toplayout)
        layout.addLayout(bottomlayout)
        self.setLayout(layout)
        self.reset_display()
        setTabOrders(self.min, self.sec, self.btn, self.min)
        self.min.setFocus()
        self.min.selectAll()
        self.resize(300, 100)
        QObject.connect(self.btn, SIGNAL("clicked()"), self.start)
        def select_sec():
            self.sec.setFocus()
            self.sec.selectAll()
        QObject.connect(self.min, SIGNAL("returnPressed()"), select_sec)
        QObject.connect(self.sec, SIGNAL("returnPressed()"), self.start)
    def start(self):
        def err(msg): 
            QMessageBox.warning(self, "Timer", msg)
        secstr = self.sec.text().strip()
        minstr = self.min.text().strip()
        if not minstr:
            err("分を入力してください")
            return
        if not secstr:
            err("秒を入力してください")
            return
        try:
            m = int(minstr)
        except ValueError as e:
            err("分を半角数字で入力してください")
            return
        try:
            s = int(secstr)
        except ValueError as e:
            err("秒を半角数字で入力してください")
            return
        self.min.setEnabled(False)
        self.sec.setEnabled(False)
        self.btn.setText("Stop")
        QObject.disconnect(self.btn, SIGNAL("clicked()"), self.start)
        QObject.connect(self.btn, SIGNAL("clicked()"), self.stop)
        self.timer = TimerThread(self, m * 60 + s)
        QObject.connect(self.timer, SIGNAL('tick(int)'), self.tick)
        QObject.connect(self.timer, SIGNAL('finish()'), self.finish)
        self.timer.start()
    def stop(self):
        self.timer.stop()
        self.sec.setEnabled(True)
        self.min.setEnabled(True)
        self.setWindowTitle("Timer")
        self.min.setFocus()
        self.min.selectAll()
        self.btn.setText("Start")
        QObject.disconnect(self.btn, SIGNAL("clicked()"), self.stop)
        QObject.connect(self.btn, SIGNAL("clicked()"), self.start)
    def tick(self, remain):
        m, s = remain // 60, remain % 60
        self.min.setText(str(m))
        self.sec.setText(str(s))
        self.setWindowTitle("残{0}分{1}秒".format(m, s))
    def finish(self):
        self.stop()
        self.reset_display()
        QMessageBox.information(self, "Timer", "時間です")
    def reset_display(self):
        self.min.setText("0")
        self.sec.setText("0")
        self.setWindowTitle("Timer")
def main():
    global app
    app = QApplication(sys.argv)
    w = TimerWindow()
    w.show()
    app.exec_()
if __name__ == "__main__":
    import doctest
    doctest.testmod()
    main()

PyQt QListWidget サンプル

シグナルはとりあえず後回し

f:id:togari_takamoto:20120312172044p:plain
f:id:togari_takamoto:20120312172014p:plain
量が増えると勝手にスクロールバーが出る

#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore

class Example(QtGui.QWidget):
    def __init__(self):
        super(Example, self).__init__()
        self.initUI()
    def initUI(self):
        listWidget = QtGui.QListWidget(self)
        QtGui.QListWidgetItem("Oak", listWidget)
        listWidget.addItem(QtGui.QListWidgetItem("Pine"))
        newItem = QtGui.QListWidgetItem()
        newItem.setText("itemText")
        listWidget.insertItem(1, newItem)
        listWidget.setCurrentRow(2)#Pineが選択された状態で起動される
        print(listWidget.currentItem().text())#Pine
        print(listWidget.currentRow())#2
        print(listWidget.count())#3
        print(listWidget.item(1).text())#newItem
        print(listWidget.takeItem(0).text())#Oak 取得&削除
        print(listWidget.count())#2
        listWidget.move(10, 10)
        self.move(300, 300)
        self.setWindowTitle('Main window')
        self.show()
def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

PyQt QComboBox サンプル

Tutorialからだいたいそのまま

f:id:togari_takamoto:20120312162734p:plain

#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore

class Example(QtGui.QWidget):
    def __init__(self):
        super(Example, self).__init__()
        self.initUI()
    def initUI(self):
        combo = QtGui.QComboBox(self)
        combo.addItem("Ubuntu")
        combo.addItem("Mandriva")
        combo.addItem("Fedora")
        combo.addItem("Red Hat")
        combo.addItem("Gentoo")

        combo.activated.connect(self.onActivated)
        combo.activated[str].connect(self.onActivatedstr)
        combo.move(10, 10)
        self.move(300, 300)
        self.setWindowTitle('QtGui.QComboBox')
        self.show()
    def onActivated(self,number):
        print(number)#0,1,2,3,4
    def onActivatedstr(self,text):
        print(text)#Ubuntu,Mandriva,Fedora,Red Hat,Gentoo
def main():
    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

PyQt scrollAreaサンプル

f:id:togari_takamoto:20120312150615p:plain

#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class Example(QMainWindow):

    def __init__(self, parent=None):
        super(Example, self).__init__(parent)

        self.setWindowTitle("Main Window")
        self.resize(200, 100)
        self.scrollArea = QScrollArea()

        self.base = QLabel()
        self.base.setPixmap(QPixmap("aaa.png"))
        self.scrollArea.setWidget(self.base)
        self.setCentralWidget(self.scrollArea)

def main():

    app = QApplication(sys.argv)
    win = Example()
    win.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

scrollAreaはsetWidgetしかないから
複数Widgetを入れるには

        self.scrollArea = QScrollArea()
        self.base = QWidget()
        self.layout = QHBoxLayout(self.base)
        #self.layout = QHBoxLayout()
        #self.base.setLayout(self.layout) #という書き方もアリ
        self.label1 = QLabel()
        self.label1.setPixmap(QPixmap("aaa.png"))
        self.label2 = QLabel()
        self.label2.setPixmap(QPixmap("bbb.png"))
        self.layout.addWidget(self.label1)
        self.layout.addWidget(self.label2)
        self.scrollArea.setWidget(self.base)
        self.setCentralWidget(self.scrollArea)

こんなかんじ?