Problem mit dem lesen von SQL Zeilen

Fragen zu Tkinter.
Antworten
roy-lueders
User
Beiträge: 8
Registriert: Montag 5. Februar 2018, 15:12

Montag 5. Februar 2018, 15:20

Hi Leute,

ich habe mich seit dem WE mit Python und Tkinter auseinander gesetzt mit einem Projekt, was aus einer SQLite DB meine daten auslesen soll und dann eine Verbindung zu dem jeweiligen PC herstellen soll

Code: Alles auswählen

# -*- coding: utf-8 -*-
from Tkinter import *
import ttk
import tkMessageBox
import Tkinter as tk
import sqlite3 as lite
from PIL import ImageTk, Image

def start(adresse,passwort):
    print(adresse)
    print(passwort)
    #Start AnyDesk

def verbindungen(tab,pc):
    with con: 
        cur = con.cursor()    
        cur.execute("hier ist mein SQL State")
        rows = cur.fetchall()
 
        Grid.rowconfigure(tab, 1, weight=1)
        Grid.columnconfigure(tab, 0, weight=1) 

        frame=Frame(tab)
        frame.grid(row=0, column=0, sticky=N+S+E+W)

        rowing = 0
        columning = 0

        for row in rows:
            Grid.rowconfigure(frame, rowing, weight=1)
            adress_id = row[0]
            adresse = row[1]
            passwort = row[2]
            hotel_name = row[4]
            hotel_fix = str(row[5])
            server = row[6]
            
            if columning == 5:
                rowing += 1
                columning = 0

            Grid.columnconfigure(frame, columning, weight=1)

            group = LabelFrame(frame, text=hotel_name, padx=5, pady=5)
            group.grid(row=rowing, column=columning)

            image = Image.open("res/img/hotel/"+hotel_fix+".jpg")
            photo = ImageTk.PhotoImage(image)
            label = Label(group, image=photo)
            label.image = photo # keep a reference!
            label.grid(row=rowing, column=columning)

            if server == 1:
                server_img = PhotoImage(file ="res/img/server.gif")
                server = Label(group, image = server_img)
                server.image = server_img
                server.grid(row=rowing, column=columning, sticky=NE)

            play_button = Button(group, text="play",command=lambda: start(adresse,passwort))
            play_img = PhotoImage(file="res/img/play.gif")
            play_button.config(image=play_img)
            play_button.image = play_img

            play_button.grid(row=rowing, column=columning, sticky=NW)

            columning += 1

        cur.close()



main = Tk()

main.geometry('1024x768')

con = lite.connect('res/database.db')

# gives weight to the cells in the grid
rows = 0
while rows < 50:
    main.rowconfigure(rows, weight=1)
    main.columnconfigure(rows, weight=1)
    rows += 1
 
# Defines and places the notebook widget
nb = ttk.Notebook(main)
nb.grid(row=1, column=0, columnspan=50, rowspan=49, sticky='NESW')

# Adds tab 1 of the notebook
tab1 = ttk.Frame(nb)
lab = 'Frontoffice'
nb.add(tab1, text=lab)
verbindungen(tab1,lab)

main.mainloop()
Er listet alles so auf, wie ich es möchte, wenn ich aber nun auf den "play_button" klicke (egal welchen play_button) kommt auch ein print, aber immer von der letzten eingelesenen DB-Zeile.
wo liegt da mein Fehler?

vielen Dank schon mal für die Hilfe
Sirius3
User
Beiträge: 8609
Registriert: Sonntag 21. Oktober 2012, 17:20

Montag 5. Februar 2018, 15:50

@roy-lueders: vermeide Sternchenimporte. Tkinter wird üblicherweise per `import Tkinter as tk` importiert und alle Namen über tk.xxx referenziert. Benutze kein globalen Variablen. In `verbindungen` kommt auf magische Weise `con`, pc wird dagegen gar nicht benutzt. `lite` ist ein komischer Name für `sqlite3` warum überhaupt die Umbenennung? Statt rowing und columning von hand zu zählen, benutze enumerate und divmod. `label`, `server` und `play_button` sind alle Kinder von `group`. Da machen die grid-Parameter jeweils keinen Sinn. Alles ab Zeile 72 gehört auch in eine Funktion, die man üblicherweise `main` nennt.

Zum Problem: genau wegen dem von Dir beobachteten Verhalten sollte man lambda nicht verwenden, benutze functools.partial statt dessen.
roy-lueders
User
Beiträge: 8
Registriert: Montag 5. Februar 2018, 15:12

Montag 5. Februar 2018, 16:25

Grüße,

ersteinmal danke für die vielen Hinweise, wie gesagt ich fange grad erst an.
pc wird für "cur.execute("SELECT * FROM...." genommen.

die ganzen Fehler versuch ich mal zu entfernen und wegen dem eigentlichen Problem. Das raff ich garnicht, kannst du mir da ein beispiel geben?
__deets__
User
Beiträge: 3712
Registriert: Mittwoch 14. Oktober 2015, 14:29

Montag 5. Februar 2018, 16:52

Wurde vor gerade mal 1.5 Monaten hier diskutiert. viewtopic.php?t=41785
roy-lueders
User
Beiträge: 8
Registriert: Montag 5. Februar 2018, 15:12

Montag 5. Februar 2018, 19:51

vielen Dank.

aber ich glaube ich bin zu doof dazu. Ich versteh das mit dem functools.partial überhaupt nicht.

Bzw. müsste es dann so sein?

Code: Alles auswählen

def partial(func, adresse, passwort):
    def start(adresse, passwort):
        args = 'echo ' + passwort +' | "AnyDesk.exe" "' + adresse + '" --with-password'
        subprocess.call(args, stdout=FNULL, stderr=FNULL, shell=False)
Wenn es so wäre, wie müsste denn dann der Button Command aussehen?
Sirius3
User
Beiträge: 8609
Registriert: Sonntag 21. Oktober 2012, 17:20

Montag 5. Februar 2018, 19:56

partial ist einfach nur der Ersatz für das nicht funktionierende lambda. Statt

Code: Alles auswählen

command=lambda: start(adresse,passwort)
schreibst Du

Code: Alles auswählen

command=partial(start, adresse, passwort)
Und statt Du in `start` eine Code-Injection-Lücke einfängst, schreibst Du

Code: Alles auswählen

def start(adresse, passwort):
    process = subprocess.Popen(["AnyDesk.exe", adresse, "--with-password"], stdin=subprocess.PIPE)
    process.communicate(passwort + "\n")
roy-lueders
User
Beiträge: 8
Registriert: Montag 5. Februar 2018, 15:12

Donnerstag 8. Februar 2018, 10:37

Hi Leute,

vielen dank erstmal bist hier her. Es läuft erstmal wie gewünscht.
Jetzt habe ich noch zwei Baustellen.

Ich habe das "start"script von Sirius3 ein gebunden.
Nun ist es aber so, dass Anydesk startet ich aber in meiner App keinen zweiten Button klicken kann.
Kann ich das irgendwie ändern?

Und wie bekomm ich in den Tabs einen vertikalen Scrollbalken hin?

Ich kann euch gern per Anfrage mal das Skript zukommen lassen.
__deets__
User
Beiträge: 3712
Registriert: Mittwoch 14. Oktober 2015, 14:29

Donnerstag 8. Februar 2018, 11:03

Dein Skript wartet mit dem communicate, bis der Kind-Prozess beendet ist. Wenn du das nicht willst, lass das communicate weg.

EDIT: Sirius3 hat natuerlich recht. Ohne write waere auch wieder oede, da hab' ich nicht genau genug hingeschaut.
Zuletzt geändert von __deets__ am Donnerstag 8. Februar 2018, 11:06, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 8609
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 8. Februar 2018, 11:04

`communicate` blockiert auch, bis das externe Programm fertig ist. Wenn Du das nicht willst, mußt Du process.stdin.write benutzen.
roy-lueders
User
Beiträge: 8
Registriert: Montag 5. Februar 2018, 15:12

Donnerstag 8. Februar 2018, 11:14

Danke Jungs, läuft.

Und das mit dem Scrollen?
Antworten