Site Tools


pyqtexample

Код взят из книги: http://unicross.narod.ru/pyqt/

Обрабатываем задачи в отедьном треде, а с основным окном работаем через сигналы.

# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui

class MyThread(QtCore.QThread):
    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)

    def run(self):
        for i in range(1, 21):
            self.sleep(3)
# "Засыпаем" на 3 секунды
# Передача данных из потока через сигнал
            self.emit(QtCore.SIGNAL("mysignal(QString)"), "i = %s" % i)

class MyWindow(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.label = QtGui.QLabel("Нажмите кнопку для запуска потока")
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.button = QtGui.QPushButton("Запустить процесс")
        self.vbox = QtGui.QVBoxLayout()
        self.vbox.addWidget(self.label)
        self.vbox.addWidget(self.button)
        self.setLayout(self.vbox)
        self.thread = MyThread()
        # Создаем экземпляр класса
        self.connect(self.button, QtCore.SIGNAL("clicked()"), self.on_clicked)
        self.connect(self.thread, QtCore.SIGNAL("started()"), self.on_started)
        self.connect(self.thread, QtCore.SIGNAL("finished()"), self.on_finished)
        self.connect(self.thread, QtCore.SIGNAL("mysignal(QString)"), self.on_change, QtCore.Qt.QueuedConnection)
    def on_clicked(self):
        self.button.setDisabled(True) # Делаем кнопку неактивной
        self.thread.start() # Запускаем поток

    def on_started(self):
        # Вызывается при запуске потока
        self.label.setText("Вызван метод on_started()")


    def on_finished(self):
        self.label.setText("Вызван метод on_finished()")
        self.button.setDisabled(False) # Делаем кнопку активной
    
    def on_change(self, s):
        self.label.setText(s)

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    window = MyWindow()
    window.setWindowTitle("Использование класса QThread")
    window.resize(300, 70)
    window.show()
    sys.exit(app.exec_())

Используем queue (очередь) для обработки заданий

Хитрости:

  • 1 - Когда тред выполняет “task = self.queue.get()” он не переходи дальше пока не получит задание. Тем самым, не создавая нагрузку в бесконечном цикле
  • 2 - Создание потоков обеспечивает то, что в “thread” передается только ссылка на объект и в этом же цикле, сигналы назначаются на саму ссылку а не на переменную “thread”. Впрочем, так всегда в python. Объект существует пока на него есть ссылка.
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import queue

class MyThread(QtCore.QThread):
    def __init__(self, id, queue, parent=None):
        QtCore.QThread.__init__(self, parent)
        self.id = id
        self.queue = queue
    def run(self):
        while True:
            task = self.queue.get() # Получаем задание
#            self.sleep(5) # Имитируем обработку
            self.emit(QtCore.SIGNAL("taskDone(int, int)"),
            task, self.id)
            # Передаем данные обратно
            self.queue.task_done()

class MyWindow(QtGui.QPushButton):
    def __init__(self):
        QtGui.QPushButton.__init__(self)
        self.setText("Раздать задания")
        self.queue = queue.Queue()
        # Создаем очередь
        self.threads = []
        for i in range(1, 10):
            # Создаем потоки и запускаем
            thread = MyThread(i, self.queue)
            self.threads.append(thread)
            self.connect(thread, QtCore.SIGNAL("taskDone(int, int)"),
            self.on_task_done, QtCore.Qt.QueuedConnection)
            thread.start()
            self.connect(self, QtCore.SIGNAL("clicked()"),
            self.on_add_task)

    def on_add_task(self):
        for i in range(0, 1100):
            self.queue.put(i)
# Добавляем задания в очередь

    def on_task_done(self, data, id):
        print(data, "- id =", id)
        # Выводим обработанные данные

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    window = MyWindow()
    window.setWindowTitle("Использование модуля queue")
    window.resize(300, 30)
    window.show()
    sys.exit(app.exec_())

Блокирование данных с использованием QMutex()

Хитрости:

# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui

debug = 1

class MyThread(QtCore.QThread):
    x = 10 # Атрибут класса
    mutex = QtCore.QMutex() # Мьютекс
    def __init__(self, id, parent=None):
        QtCore.QThread.__init__(self, parent)
        self.id = id

    def run(self):
        self.change_x()
        
    def change_x(self):
        MyThread.mutex.lock()
        # Блокируем
        print("x =", MyThread.x, "id =", self.id)
        MyThread.x += 5
        self.sleep(2)
        print("x =", MyThread.x, "id =", self.id)
        MyThread.x += 34
        print("x =", MyThread.x, "id =", self.id)
        MyThread.mutex.unlock()
        # Снимаем блокировку

class MyWindow(QtGui.QPushButton):
    def __init__(self):
        QtGui.QPushButton.__init__(self)
        self.setText("Запустить")
        self.thread1 = MyThread(1)
        self.thread2 = MyThread(2)
        self.connect(self, QtCore.SIGNAL("clicked()"), self.on_start)
    
    def on_start(self):
        self.thread1.start()
        self.thread2.start()

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    window = MyWindow()
    window.setWindowTitle("Использование класса QMutex")
    window.resize(300, 30)
    window.show()
    sys.exit(app.exec_())

Splash заставка перед запуском программы

# -*- coding: utf-8 -*-
from PyQt4 import QtGui
from PyQt4.QtCore import Qt, SIGNAL
import time

class MyWindow(QtGui.QPushButton):
    def __init__(self):
        QtGui.QPushButton.__init__(self)
        self.setText("Закрыть окно")
        self.connect(self, SIGNAL("clicked()"), QtGui.qApp.quit)

    def load_data(self, sp):
        for i in range(1, 11): # Имитируем процесс
            print("Load_data +1")
            time.sleep(2) # Что-то загружаем
            sp.showMessage("Загрузка данных... {0}%".format(i * 10),
            Qt.AlignHCenter | Qt.AlignBottom, Qt.white)
            QtGui.qApp.processEvents()
            # Запускаем оборот цикла

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    print("main | splash")
    splash = QtGui.QSplashScreen(QtGui.QPixmap("/home/konovalov/Downloads/logo3.png"), Qt.WindowStaysOnTopHint)
    splash.showMessage("Загрузка данных... 0%", Qt.AlignHCenter | Qt.AlignBottom, Qt.white)
    print("main splash |")
    splash.show() # Отображаем заставку
    QtGui.qApp.processEvents() # Запускаем оборот цикла
    window = MyWindow()
    window.setWindowTitle("Использование класса QSplashScreen")
    window.resize(300, 30)
    window.load_data(splash)
    # Загружаем данные
    window.show()
    splash.finish(window)
    # Скрываем заставку
    sys.exit(app.exec_())

Изменяем цвет объектов

# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import sys
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
window.setWindowTitle("Изменение цвета фона окна")
window.resize(300, 100)
pal = window.palette()
pal.setColor(QtGui.QPalette.Normal, QtGui.QPalette.Window, QtGui.QColor("#008800"))
pal.setColor(QtGui.QPalette.Inactive, QtGui.QPalette.Window, QtGui.QColor("#ff0000"))
window.setPalette(pal)
label = QtGui.QLabel("Текст надписи")
label.setAlignment(QtCore.Qt.AlignCenter)
label.setStyleSheet("background-color: #ffffff;")
vbox = QtGui.QVBoxLayout()
vbox.addWidget(label)
window.setLayout(vbox)
window.show()
sys.exit(app.exec_())

Изображение в качестве фона

# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import sys
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
window.setWindowTitle("Изображение в качестве фона")
window.resize(300, 100)
pal = window.palette()
pal.setBrush(QtGui.QPalette.Normal, QtGui.QPalette.Window,
QtGui.QBrush(QtGui.QPixmap("img1.png")))
window.setPalette(pal)
label = QtGui.QLabel("Текст надписи")
label.setAlignment(QtCore.Qt.AlignCenter)
label.setAutoFillBackground(True)
vbox = QtGui.QVBoxLayout()
vbox.addWidget(label)
window.setLayout(vbox)
window.show()
sys.exit(app.exec_())

Создание окна произвольной формы

Фон и форму окна можно нарисовать с использованием Альфа канала. создание альфа канала в GIMP

# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import sys
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
window.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint)
window.setWindowTitle("Создание окна произвольной формы")
window.resize(600, 300)
pixmap = QtGui.QPixmap("/home/konovalov/Alfatest.png")
pal = window.palette()
pal.setBrush(QtGui.QPalette.Normal, QtGui.QPalette.Window, QtGui.QBrush(pixmap))
pal.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, QtGui.QBrush(pixmap))
window.setPalette(pal)
window.setMask(pixmap.mask())
button = QtGui.QPushButton("Закрыть окно", window)
button.setFixedSize(150, 30)
button.move(75, 135)
QtCore.QObject.connect(button, QtCore.SIGNAL("clicked()"),
QtGui.qApp, QtCore.SLOT("quit()"))
window.show()
sys.exit(app.exec_())

Создание окна с вызовом меню правой кнопкой, основного меню и панелью инструментов

import sys
from PyQt4 import QtGui

class Example(QtGui.QMainWindow):

    def contextMenuEvent(self, event):
         self.menu = QtGui.QMenu(self.table)
         self.menu.addAction(self.PrintigConsole)
         self.menu.exec_(QtGui.QCursor.pos())
    
    def createActions(self):
         self.exitAct = QtGui.QAction('E&xit', self, shortcut='Ctrl+Q', statusTip='Exit the application', triggered=app.exit)
         
         self.PrintigConsole = QtGui.QAction("Printing console", self)
         self.PrintigConsole.setShortcut(QtGui.QKeySequence.mnemonic("&е"))
         self.PrintigConsole.triggered.connect(self.printing)

    def printing(self):
        print("Success print")
    
    def createMenus(self):
        self.menubar = self.menuBar()
        self.fileMenu = self.menuBar().addMenu("&File")
        self.fileMenu.addAction(self.exitAct)
    
    def settingsAct(self):
        pass

    def aboutAct(self):
        pass
    
    def exitAct(self):
        pass
    
    def createToolbar(self):
        self.toolbar = self.addToolBar('Toolbar')
        self.toolbar.addAction("Some")
        self.toolbar.addSeparator()
        self.toolbar.addAction("Some2")
    
    def creatStatusbar(self):
        self.statusBar()

    def __init__(self):
        super(Example, self).__init__()
    
        self.header_lbls = ['Name', 'Second Name', 'Surname', 'Birth Date', 'Phone Number', 'Skype', 'E-mail']
    
        self.table = QtGui.QTableWidget(10, 7)
        self.table.setHorizontalHeaderLabels(self.header_lbls)
        self.setCentralWidget(self.table)
    
        #ACTIONS
        self.createActions()
    
        #MENUBAR
        self.createMenus()
    
        #TOOLBAR
        self.createToolbar()
    
        #STATUSBAR
        self.creatStatusbar()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = Example()
    window.setGeometry(80, 80, 800, 600)
    window.show()
    sys.exit(app.exec_())

Передвижение по зажатой, левой кнопки мыши

from PyQt4.QtGui import QWidget, QApplication, QLabel, QHBoxLayout
from PyQt4.QtCore import Qt
import sys

class FramelessWidget(QWidget):
    def __init__(self):
        super(QWidget, self).__init__()
        self.setWindowFlags(Qt.FramelessWindowHint)
        #self.setWindowOpacity(0.5)
        layout = QHBoxLayout()
        label = QLabel('Large Label Test')
        layout.addWidget(label)
        self.setLayout(layout)
        self.setMouseTracking(True)
        self.moving = False


    def mouseMoveEvent(self, event):
        ## Use this to create the mouse 'Grab & Move'
        if self.moving: self.move(event.globalPos()-self.offset)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.moving = True; self.offset = event.pos()
        if event.button() == Qt.RightButton: self.close()

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.moving = False


if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setApplicationName("Frameless Widget")
    app.setQuitOnLastWindowClosed(True)

    window = FramelessWidget()
    window.show()

    sys.exit(app.exec_())

Drag And Drop - получить текст из сторонних приложений

import sys
from PyQt4 import QtGui
from PyQt4 import QtCore

class Drag(QtGui.QDialog):
    def __init__(self, parent=None):
        QtGui.QDialog.__init__(self, parent)
        self.setAcceptDrops(True)

    def dragEnterEvent(self, event):
        if event.mimeData().hasFormat('text/plain'):
            event.accept()

    def dropEvent(self, event):
        print(event.mimeData().text())
        event.accept()

app = QtGui.QApplication(sys.argv)
db = Drag()
db.show()
app.exec_()
You could leave a comment if you were logged in.
pyqtexample.txt · Last modified: 2012/03/24 10:02 (external edit)

Page Tools