2012-08-03 83 views
9

Tôi hiện đang cần thư viện GUI cho một dự án. Tôi quen thuộc với python và tìm thấy PyQt có thể là một lựa chọn tốt.Giới thiệu về một chương trình ví dụ PyQt

Tôi đang đọc a tutorial about PyQt, và khá bối rối về sau example program

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

""" 
ZetCode PyQt4 tutorial 

In this example, we draw text in Russian azbuka. 

author: Jan Bodnar 
website: zetcode.com 
last edited: September 2011 
""" 

import sys 
from PyQt4 import QtGui, QtCore 

class Example(QtGui.QWidget): 

    def __init__(self): 
     super(Example, self).__init__() 

     self.initUI() 

    def initUI(self):  

     self.text = u'\u041b\u0435\u0432 \u041d\u0438\u043a\u043e\u043b\u0430\ 
\u0435\u0432\u0438\u0447 \u0422\u043e\u043b\u0441\u0442\u043e\u0439: \n\ 
\u0410\u043d\u043d\u0430 \u041a\u0430\u0440\u0435\u043d\u0438\u043d\u0430' 

     self.setGeometry(300, 300, 280, 170) 
     self.setWindowTitle('Draw text') 
     self.show() 

    def paintEvent(self, event): 

     qp = QtGui.QPainter() 
     qp.begin(self) 
     self.drawText(event, qp) 
     qp.end() 

    def drawText(self, event, qp): 

     qp.setPen(QtGui.QColor(168, 34, 3)) 
     qp.setFont(QtGui.QFont('Decorative', 10)) 
     qp.drawText(event.rect(), QtCore.Qt.AlignCenter, self.text)   


def main(): 

    app = QtGui.QApplication(sys.argv) 
    ex = Example() 
    sys.exit(app.exec_()) 


if __name__ == '__main__': 
    main() 

Ở đây, trong chức năng chính, một đối tượng Ví dụ được tạo ra, do đó __init__() chức năng, initUI() được gọi. Câu hỏi của tôi là ở đâu chức năng paintEvent() được gọi là ?? kể từ khi chúng tôi chạy chương trình, self.text(some Russian letters) sẽ xuất hiện chính xác trên tiện ích.

Nói cách khác, những gì hiện sys.exit(app.exec_()) thực sự làm gì? tại sao nó sẽ gọi hàm paintEvent()?

Cảm ơn!

Trả lời

6

Từ PyQt docs:

int QApplication.exec_()

Enters vòng lặp sự kiện chính và đợi cho đến khi exit() được gọi, sau đó trả về giá trị đã được thiết lập để exit() (đó là 0 nếu exit() được gọi qua quit()).

Cần gọi hàm này để bắt đầu xử lý sự kiện. Vòng lặp sự kiện chính nhận các sự kiện từ hệ thống cửa sổ và gửi các sự kiện này đến các tiện ích ứng dụng.

Từ another source:

sys.exit(app.exec_())

Cuối cùng, chúng ta bước vào mainloop của ứng dụng . Việc xử lý sự kiện bắt đầu từ thời điểm này. Mainloop nhận các sự kiện từ hệ thống cửa sổ và gửi chúng đến các tiện ích ứng dụng . Vòng lặp chính kết thúc, nếu chúng tôi gọi phương thức exit() hoặc tiện ích chính bị hủy. Phương pháp sys.exit() đảm bảo lối ra sạch sẽ. Môi trường sẽ được thông báo, cách ứng dụng kết thúc.

Phương thức exec_() có dấu gạch dưới. Đó là vì exec là từ khóa Python. Và do đó, exec_() đã được sử dụng thay thế.

Về painting:

4.2.1. Khi Tranh Xảy ra

Phương pháp paintEvent() được gọi tự động khi

  • phụ tùng bạn được hiển thị cho lần đầu tiên.

  • Sau khi cửa sổ đã được di chuyển để hiển thị một số phần (hoặc tất cả) của tiện ích .

  • Cửa sổ trong đó tiện ích con nằm được khôi phục sau khi được thu nhỏ.

  • Cửa sổ trong đó tiện ích con được định lại kích thước.

  • Người dùng chuyển từ máy tính khác sang màn hình mà cửa sổ của tiện ích nằm.

Bạn có thể tạo sự kiện sơn theo cách thủ công bằng cách gọi QWidget::update(). QWidget::update() xóa tiện ích trước khi tạo sự kiện sơn. Bạn có thể chuyển đối số cho update(), có thể hạn chế chỉ sơn đến các khu vực (hình chữ nhật, cụ thể) cần đến. Hai hình thức tương đương của phương pháp là QWidget::update (int x, int y, int width, int height)QWidget::update (QRect rectangle), trong đó xy cung cấp cho góc ở góc trên bên trái của hình chữ nhật và chiều rộng và chiều cao là hiển nhiên. Bởi vì update() đặt một sự kiện sơn vào hàng đợi sự kiện, không có bức tranh xảy ra cho đến khi phương pháp hiện tại thoát và kiểm soát trả về trình xử lý sự kiện. Đây là một điều tốt vì các sự kiện khác có thể là đang chờ xử lý và các sự kiện cần được xử lý theo cách kịp thời để GUI hoạt động trơn tru.

Bạn cũng có thể gọi bức tranh của các widget bằng cách gọi QWidget::repaint (int x, int y, int width, int height, bool erase) (hoặc một trong vài hình thức thuận tiện-method), nơi mà tất cả các đối số có ý nghĩa giống như trong trường hợp của các phương pháp update(), và xóa kể sơn lại xem có nên xóa hình chữ nhật trước khi vẽ. repaint() gọi paintEvent() trực tiếp. Nó không đặt một sự kiện sơn vào hàng đợi sự kiện, vì vậy hãy sử dụng phương thức này cẩn thận. Nếu bạn cố gắng gọi số repaint() nhiều lần từ một số vòng lặp đơn giản để tạo hoạt ảnh, ví dụ, hình động sẽ được rút ra, nhưng phần còn lại của giao diện người dùng của bạn sẽ không phản hồi vì các sự kiện tương ứng với lần nhấp nút chuột, bàn phím máy ép , v.v. sẽ đợi trong hàng đợi. Ngay cả khi bạn không phải là thực hiện tác vụ có khả năng tốn thời gian làm hoạt ảnh, thì đó là thường tốt hơn để sử dụng update() để giúp giữ cho GUI của bạn luôn hoạt động.

Nếu bạn vẽ thứ gì đó trên tiện ích của mình bên ngoài paintEvent(), bạn vẫn cần bao gồm logic và các lệnh cần thiết để vẽ điều tương tự trong paintEvent(). Nếu không, bức tranh bạn đã làm sẽ biến mất vào lần tiếp theo tiện ích được cập nhật.

+0

Cảm ơn bạn đã giải thích chi tiết như vậy. – Junjie

1

app.exec_() bắt đầu vòng lặp chính qt, kết thúc khi mọi tiện ích được tạo bị hủy (ví dụ: bằng cách đóng cửa sổ của nó). Hàm paintEvent là một phương thức mà bạn có thể quá tải từ một lớp con QWidget như lớp Example đã cho, được gọi khi QT hiển thị, cập nhật hoặc vẽ lại Widget.

Bạn có thể tra cứu những thứ này trong Qt documentation hoặc PyQt Documentation (hầu hết chỉ là bản sao Tài liệu QT ở định dạng khác, nhưng đôi khi chứa một số thông tin có giá trị về những thứ cụ thể PyQt).

1

Nó trở nên rõ ràng hơn khi có một số kinh nghiệm với lập trình cấp thấp, ví dụ trong Winapi hoặc bộ công cụ X bằng ngôn ngữ C. PyQt là một bộ công cụ cấp cao (rất). Nó đi kèm với một chức năng tích hợp rất lớn. Ví dụ tương tự sẽ yêu cầu hàng trăm hoặc có thể hàng ngàn dòng mã C. Kết quả là, có rất nhiều việc xảy ra trên đằng sau hậu trường. Ai đó đã tạo ra mã giao dịch với bức tranh ở một mức độ cơ bản. Lập trình GUI rất phức tạp và với các bộ công cụ GUI hiện đại, trình lập trình ứng dụng được che chắn khỏi sự phức tạp này. Nó là không thể tránh khỏi mà các lập trình viên đang bối rối nếu họ không biết tất cả các chi tiết kỹ thuật.

Trong PyQt, chúng tôi chủ yếu giải quyết các sự kiện theo hai cách. Chúng ta kết nối các tín hiệu vào các khe hoặc thực thi lại các trình xử lý sự kiện (một trình xử lý sự kiện là một từ đồng nghĩa cho một khe). Ví dụ được cung cấp được kế thừa từ QtGui.QWidget đã có sẵn một số mã vẽ. Để làm bức tranh tùy chỉnh của chúng tôi, chúng tôi phải thực hiện lại bộ xử lý hiện tại paintEvent() . Tùy thuộc vào tình hình, chúng tôi có thể hoặc không thể gọi phương thức paintEvent() của phụ huynh.

sys.exit(app.exec_()) không gọi phương thức paintEvent(). Phương thức exec_() bắt đầu một vòng lặp sự kiện. Vòng lặp sự kiện bắt và gửi các sự kiện. Sự kiện sơn được kích hoạt bởi người dùng hoặc bởi hệ điều hành. Ví dụ: khi chúng tôi khởi chạy ví dụ, sự kiện sơn được kích hoạt hai lần. (Đặt một dòng print "Event occurred" trong trình xử lý sự kiện để xem số lần phương thức này được gọi.) Thay đổi kích thước cửa sổ, mất hoặc lấy tiêu điểm, thu nhỏ hoặc phóng to cửa sổ, tất cả các sự kiện này sẽ được kích hoạt.

Các vấn đề liên quan