2010-03-20 34 views
6

Tôi gặp sự cố, nơi tôi muốn chạy một số chức năng dòng lệnh từ chương trình python bằng GUI. Tôi không biết liệu sự cố của tôi có phải là cụ thể đối với PyQt4 hoặc nếu nó có liên quan đến việc sử dụng mã python của tôi không hợp lệ.Nhãn trong PyQt4 GUI không cập nhật với mỗi vòng lặp FOR for

Điều tôi muốn làm là dán nhãn trên GUI thay đổi giá trị văn bản để thông báo cho người dùng biết lệnh nào đang được thực hiện. Tuy nhiên, vấn đề của tôi nảy sinh khi tôi chạy một vài lệnh bằng cách sử dụng một số cho vòng lặp. Tôi muốn nhãn tự cập nhật với mỗi vòng lặp, tuy nhiên, chương trình không cập nhật nhãn GUI với mỗi vòng lặp, thay vào đó, nó chỉ cập nhật chính nó khi hoàn thành toàn bộcho vòng lặp và chỉ hiển thị lệnh cuối cùng đã được thực hiện.

Tôi đang sử dụng PyQt4 cho môi trường GUI của mình. Và tôi đã thiết lập rằng biến văn bản cho nhãn thực sự đang được cập nhật với mọi vòng lặp, nhưng, nó không thực sự hiển thị trực quan trong GUI.

Có cách nào để tôi buộc nhãn cập nhật không? Tôi đã thử các phương thức cập nhật ()repaint() trong vòng lặp, nhưng chúng không tạo ra bất kỳ sự khác biệt nào.

Tôi thực sự đánh giá cao bất kỳ trợ giúp nào. Cảm ơn bạn.

Ronny.

Đây là mã tôi đang sử dụng:

# -*- coding: utf-8 -*- 
import sys, os 
from PyQt4 import QtGui, QtCore 
Gui = QtGui 
Core = QtCore 

# ================================================== CREATE WINDOW OBJECT CLASS 
class Win(Gui.QWidget): 
    def __init__(self, parent = None): 
     Gui.QWidget.__init__(self, parent) 

     # --------------------------------------------------- SETUP PLAY BUTTON 
     self.but1 = Gui.QPushButton("Run Commands",self) 
     self.but1.setGeometry(10,10, 200, 100) 

     # -------------------------------------------------------- SETUP LABELS 
     self.label1 = Gui.QLabel("No Commands running", self) 
     self.label1.move(10, 120) 

     # ------------------------------------------------------- SETUP ACTIONS 
     self.connect(self.but1, Core.SIGNAL("clicked()"), runCommands) 


# ======================================================= RUN COMMAND FUNCTION 
def runCommands(): 
    for i in commands: 
     win.label1.setText(i)  # Make label display the command being run 
     print win.label1.text()  # This shows that the value is actually 
            # changing with every loop, but its just not 
            # being reflected in the GUI label 
     os.system(i) 

# ======================================================================== MAIN 

# ------------------------------------------------------ THE TERMINAL COMMANDS 
com1 = "espeak 'senntence 1'" 
com2 = "espeak 'senntence 2'" 
com3 = "espeak 'senntence 3'" 
com4 = "espeak 'senntence 4'" 
com5 = "espeak 'senntence 5'" 
commands = (com1, com2, com3, com4, com5) 

# --------------------------------------------------- SETUP THE GUI ENVIRONMENT 
app = Gui.QApplication(sys.argv) 
win = Win() 
win.show() 

sys.exit(app.exec_()) 

Trả lời

10

Nhãn được cập nhật tất cả các quyền, nhưng GUI không vẽ lại trước khi kết thúc vòng lặp của bạn.

Đây là những gì bạn có thể làm gì về nó:

  • Di chuyển vòng dài chạy của bạn để một sợi thứ cấp, vẽ GUI đang xảy ra trong các chủ đề chính.

  • Gọi app.processEvents() trong vòng lặp của bạn. Điều này cho phép Qt có cơ hội xử lý các sự kiện và vẽ lại GUI.

  • Chia tay vòng lặp của bạn và để cho nó chạy bằng QTimer với một thời gian chờ của 0.

Sử dụng một sợi là lựa chọn tốt nhất, nhưng liên quan đến công việc khá hơn một chút so với chỉ gọi processEvents . Làm nó với một bộ đếm thời gian là cách cũ thời và không được recommanded nữa. (xem tài liệu)

+0

Cảm ơn bạn rất nhiều! Tôi đã tìm thấy ứng dụng đó.processEvents() chỉ thay đổi nhãn sau khi mỗi lệnh đã được hoàn thành, đã quá muộn và cũng bỏ qua một vài lệnh. Tác phẩm đã tạo ra một đối tượng QThread mới với phương thức chạy và gọi phương thức chạy khi nhấn nút. Đây có phải là ý của bạn không? Đây là mã tôi đã sử dụng. Tôi chưa bao giờ học về luồng trước đây, vì vậy hãy cho tôi biết nếu tôi đã áp dụng nó một cách không chính xác. RunCommands lớp (Core.QThread): def chạy (tự): for i in lệnh: win.label1.setText (i) os.system (i) – Ronny

+0

Ohh, geez, nhận xét didnt in ra với các dòng và tab mới tôi đã nhập: ( – Ronny

+0

@Ronny: Điều đó nghe có vẻ đúng, nhưng bạn nên gọi 'start() 'thay vì' run() '. –

2

Bạn có một sự hiểu lầm cơ bản về cách thức hoạt động của GUI. GUI Qt phải chạy trong vòng lặp sự kiện của riêng nó. Vòng lặp của bạn chạy thay vào đó, và GUI không thể thực hiện công việc của nó giữa các lần thực hiện vòng lặp của bạn. Đó là, trong khi vòng lặp for của bạn đang chạy mã GUI không nhận được thời gian CPU và sẽ không cập nhật.

Bạn có thể thiết lập bộ hẹn giờ với sự kiện và thực thi mã của bạn trong trình xử lý sự kiện này một khoảng thời gian nhất định - điều này sẽ giải quyết được sự cố của bạn.

+1

Cảm ơn lời giải thích trong đoạn 1 trả lời của bạn. Bây giờ nó giúp tôi hiểu thêm về những gì đang diễn ra, và giúp tôi hiểu được lý do đằng sau câu trả lời của Georg cũng tốt hơn một chút. Tuy nhiên tôi không hiểu giải pháp thực tế bạn đang đề xuất. Tôi là một người mới bắt đầu rất nhiều trong lập trình. Có lẽ một phác thảo phác thảo đơn giản của mã sẽ được tham gia sẽ rất hữu ích. Mặc dù bây giờ tôi đã tìm thấy một giải pháp mà dường như làm việc, tôi sẽ rất tò mò muốn tìm hiểu thay thế được đề xuất của bạn. – Ronny

+0

@Ronny: tìm hiểu về QTimer và xem xét một số ví dụ về việc sử dụng nó - tôi nghĩ nó sẽ trở nên rõ ràng đối với bạn –

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