Trädvy Permalänk
Medlem
Plats
~/Karlstad
Registrerad
Dec 2005

Threads UI och Python

Jag har skrivit ett eget program med ett UI(QT). Programmet är skrivet för python3 så jag använder mig givetvis utav PyQT-biblioteket.
Mitt problem är att UI't inte uppdaterar sig/är responsivt när jag anropar en funktion via en knapp.
Låt oss säga att jag anropar en funktion som ligger och kör i 30 sekunder, då är UI't låst under denna tid.
Vad jag förstått så beror detta på att "uppritningen" av UI't är en loop och då jag anropar en funktion som tar upp hela processen så gör detta att UI't inte kan uppdatera sig?

Vad jag då förstått vidare så bör man då dela upp programmet så det körs i olika trådar och det är här jag skulle behöva en liten push hur jag ska lägga upp det(eller om det finns en alternativ lösning).

Ska bifoga en snutt av koden som jag tror kan vara intressant för detta:

if __name__ == "__main__": import sys, socket, os from PyQt4 import QtCore, QtGui global settings app = main_ui.QtGui.QApplication(sys.argv) MainWindow = main_ui.QtGui.QMainWindow() ui = main_ui.Ui_MainWindow() ui.setupUi(MainWindow) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(None) settings = startUp() MainWindow.show() QtCore.QObject.connect(ui.buttonconnect, QtCore.SIGNAL("clicked()"), connectPi) QtCore.QObject.connect(ui.buttonshutdown, QtCore.SIGNAL("clicked()"), shutdownserver) QtCore.QObject.connect(ui.buttonsetsave, QtCore.SIGNAL("clicked()"), saveSettings) QtCore.QObject.connect(ui.buttonmanspindle, QtCore.SIGNAL("clicked()"), spindleMotor)

Koden ovan är egentligen "huvudkoden" och resten är enbart diverse funktioner som anropas av knapptryckningar i UI't som synes. Har mycket mer knappar men spelar ju ingen roll antar jag för detta problem.

Så tänker jag rätt att jag vill lägga MainWindow.show() i en tråd och sen på något sätt få in alla funktioner i en annan?
Och hur görs detta isåfall rent praktiskt?

Vad det handlar om är min bygglogg där jag bygger en liten CNC-maskin, problemet som uppstår är att vid körning så uppdateras inte XYZ-kordinaterna i realtid utan kanske en gång i minuten eller så, antar att detta beror på trådhanteringen(som är obefintlig idag)?

Vore tacksam för en knuff i rätt riktning då det skulle få min mjukvara att uppföra sig lite proffsigare
Kan givetvis bifoga mer kod om det är nödvändigt^^

Skulle kunna skriva en testkod här för att göra det tydligare:

def delay(): time.sleep(60) #importerar och skapar nödvändiga ui-objekt här MainWindow.show() QtCore.QObject.connect(ui.buttonconnect, QtCore.SIGNAL("clicked()"), delay)

I koden ovan skulle UI't inte gå att exempelvis ändra storlek på under tiden som delay körs. Hur fixar man denna så att det går?

Bara gammalt skräp...

Trädvy Permalänk
Hedersmedlem
Plats
Linköping
Registrerad
Apr 2004
Trädvy Permalänk
Hedersmedlem
Plats
Linköping
Registrerad
Okt 2006

Japp, du kommer behöva trådhantering och att lösa alla problem som det innebär. Har du inte pysslat med trådar tidigare bör du ta lite tid att lära dig det och förstå konceptet. Du kommer behöva jobba med delade resurser och hur man hanterar det så att man alltid läser och skriver utan att det blir fel.

Trädvy Permalänk
Medlem
Plats
~/Karlstad
Registrerad
Dec 2005

Hmm ok, antar att jag får börja med något simpelt först innan jag ger mig på att anpassa mitt program då det kanske är krångligare än man tror samt att man får väl lite mer förståelse då vad som händer.
Hade säkert varit enklare att vetat om detta från start istället för att gå in nu i efterhand och pula runt^^
Ska titta på guiden som Elgot länkat till och se om jag kan begripa något av den^^
Lär väl återkomma när jag stöter på patrull

Bara gammalt skräp...

Trädvy Permalänk
Medlem
Plats
~/Karlstad
Registrerad
Dec 2005

Ok, detta visade sig vara lite krångligt att implementera såhär i efterhand, vette fan om det är värt det i dagsläget...
Finns det något sätt att "tvinga" UI't att uppdatera sig?
Har ett ställe i koden där det skulle vara lämpligt nämligen som ser ut på följande sätt:

#tar emot lite data från servern s.recv() #behandlar denna data #Här skulle det vara lämpligt att tvinga Ui't att uppdatera sig om möjligt innan jag utför nedanstående typ Force.ui.update() #skickar den behandlade datan till serven s.send()

@Shimonu
Något sätt du vet om?

Bara gammalt skräp...

Trädvy Permalänk
Hedersmedlem
Plats
Linköping
Registrerad
Okt 2006
Skrivet av bardbard:

Ok, detta visade sig vara lite krångligt att implementera såhär i efterhand, vette fan om det är värt det i dagsläget...
Finns det något sätt att "tvinga" UI't att uppdatera sig?
Har ett ställe i koden där det skulle vara lämpligt nämligen som ser ut på följande sätt:

#tar emot lite data från servern s.recv() #behandlar denna data #Här skulle det vara lämpligt att tvinga Ui't att uppdatera sig om möjligt innan jag utför nedanstående typ Force.ui.update() #skickar den behandlade datan till serven s.send()

@Shimonu
Något sätt du vet om?

Nu har jag inte jobbat med Qt så jag kan inte speciellt mycket om det. Efter några sekunders googlande har jag hittat det här, är det någon hjälp?

http://stackoverflow.com/questions/12410433/forcing-the-qt-gu...

Trädvy Permalänk
Hedersmedlem
Plats
Linköping
Registrerad
Apr 2004

Ofta vill man nog låta gränssnittet sköta sin egen uppdatering; det borde räcka att uppdatera kontrolleras värden. Fungerar det fast för långsamt? Eller händer inget alls?

Trädvy Permalänk
Medlem
Plats
~/Karlstad
Registrerad
Dec 2005
Skrivet av Elgot:

Ofta vill man nog låta gränssnittet sköta sin egen uppdatering; det borde räcka att uppdatera kontrolleras värden. Fungerar det fast för långsamt? Eller händer inget alls?

Det som det gäller är min maskin jag bygger och skriver mjukvaran till. Om du vet hur en CNC-maskin fungerar så kör man ju en sekvens av instruktioner(ett program) hur maskinen ska köra, exempelvis
Gå till X0
X2 Y3
...
Program slut

Ett program kan bestå av ett antal 1000 rader med kordinater som maskinen ska köra till och ett program kan pågå i timmar om man så vill.
Vad som händer när jag kör är att servern(Raspberry pi) utför instruktionerna och beräknar hela tiden vart i rymden verktyget befinner sig(XYZ). När en instruktion är färdig så skickar servern koordinaterna till min klient så att den kan uppdatera UI't så jag kan se vilket XYZ jag befinner mig på.

Vad som händer nu är att servern skickar XYZ-värde till klienten, när klienten har fått detta så skickar den en ny instruktion till servern för nästa förflyttning o.s.v.
I.om att detta sker på direkten så är känslan att UI't inte hinner uppdatera sig trots att jag uppdaterar värdena på mina labels i UI't.
Det är det jag beskrev lite ovan med mina send och recieves och därför hade det varit lämpligt att tvinga ui't att uppdatera sig på den positionen.

UI't uppdateras dock ibland, kanske varannan minut eller så så lite feedback får jag ju, men det hade varit trevligt att få uppdateringar i realtid givetvis...
Men det kanske är som du säger att jag får bita i det sura äpplet och verkligen styra upp det hela med trådar för att få en bra långsiktig lösning..
Gjorde ett enkelt UI för test och fick det att fungera, men svårare att implementera i mitt befintliga program då det börjar bli så mycket rader med kod

Tackar ödmjukast för svar iaf, ska kika och prova Shimonus länk där om det kan vara en temporär lösning iaf.

Det verkar som att

app.processEvents()

gör det jag vill iaf men att olika trådar rekommenderas

Bara gammalt skräp...

Trädvy Permalänk
Hedersmedlem
Plats
Linköping
Registrerad
Apr 2004

Problemet är nog att du (som sagt) blockerar huvudtråden när du väntar på uppdateringar. Om du inte vill använda trådar bör man kunna använda asynkrona metoder; en socket genererar till exempel signalen readyRead när det finns ny data, så om man lyssnar på den behöver man inte vänta aktivt.