Я использую многопоточность, так зачем все время беспокоиться о моем графическом интерфейсе? - PullRequest
0 голосов
/ 02 апреля 2019

Хорошо, у меня возникли проблемы несколько дней назад, и кто-то помог мне с проступанием, но мой код был действительно уродливым (я совершенно новичок в кодировании), теперь я пытаюсь сделать его лучше и более умным способом, но теперь мой графический интерфейс все время зависает , Я пытался сделать это в пути, как мой последний код, но в этот раз это не сработало. Что мне делать в этот раз, я не могу понять это, но хочу понять это. полезные советы и рекомендации? Или лучшие способы сделать это умнее, быстрее и мощнее, или mybae the gui более Beautyfule?

import time
import sys
from tkinter import *
import threading


root = Tk()

root.geometry("600x400")


global start
start = 1


def startUp():
    user_input()
    thr = threading.Thread(target=user_input)
    thr.start()



def user_input():
    global nameInput
    global start
    nameInput = textBox.get("1.0","end-1c")
    start = 0
    if start < 1:
        while True:
            apex = ApexLegends("APIKey")
            player = apex.player(nameInput)
            print("Gesamt Kills: " + player.kills + "\n" + 'Gesamt Damage: ' + player.damage)
            time.sleep(3)
    else:
        print("stop")


anleitung=Label(text="Gib einen Spielernamen ein und drücke Start")
anleitung.pack()

textBox=Text(root, height=1, width=30)
textBox.pack()

startButton=Button(root, height=1, width=10, text="Start", command=lambda:startUp())
startButton.pack()



Ответы [ 3 ]

1 голос
/ 02 апреля 2019

Tkinter не предназначен для доступа более чем к одному потоку. Вот отличный ответ одного из парней, который очень глубоко понимает, как работает tcl & tk (библиотеки, от которых зависит tkinter), объясняя, почему это так.

Обратный вызов функции Python из Tkinter Tcl падает в Windows

Это первый из двух абзацев в этом ответе:

Каждый объект интерпретатора Tcl (т. Е. Контекст, который знает, как запустить процедуру Tcl) можно безопасно использовать только из потока ОС, который его создает. Это связано с тем, что Tcl не использует глобальную блокировку интерпретатора, такую ​​как Python, а вместо этого широко использует специфичные для потока данные, чтобы уменьшить количество внутренних блокировок. (Хорошо написанный код Tcl может использовать это для очень большого масштабирования на подходящем оборудовании.)

0 голосов
/ 02 апреля 2019

Привет, @Trason. Я поиграл с твоим кодом и предлагаю ооо подход.

В приведенном ниже коде я пытаюсь адаптировать функциональный скрипт к твоему коду.

СначалаЯ использую переменную как

self.nameInput = tk.IntVar ()

для хранения ввода пользователя на

tk.Entry (w, bg = 'white', textvariable = self.nameInput) .pack ()

Я использовал виджет Entry вместо Text, но он должен быть таким же.

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

Слушайте, я изменил вашу переменную 'start' с помощью 'check', потому что start является зарезервированным словом

вМодуль потока Python.

Я пытался воссоздать функциональность вашего кода.

Попробуйте импортировать и использовать ваши ApexLegends.

import tkinter as tk

import threading
import queue
import datetime
import time

class MyThread(threading.Thread):

    def __init__(self, queue,nameInput):
        threading.Thread.__init__(self)

        self.queue = queue
        self.nameInput = nameInput
        self.check = True

    def stop(self):
        self.check = False

    def run(self):

        while self.check:
            # apex = ApexLegends("APIKey")
            #player = apex.player(self.nameInput.get())
            x = "Gesamt Kills: " + "player.kills" + "\n" + 'Gesamt Damage: ' + "player.damage"+ "\n"
            s = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            msg = "{} datetime: {} nameInput {}".format(x,s,self.nameInput.get())
            time.sleep(3)
            self.queue.put(msg)


class App(tk.Frame):

    def __init__(self,):

        super().__init__()

        self.master.title("Hello World")
        self.master.protocol("WM_DELETE_WINDOW",self.on_close)

        self.queue = queue.Queue()

        self.my_thread = None
        self.nameInput = tk.IntVar()

        self.init_ui()

    def init_ui(self):

        self.f = tk.Frame()

        w = tk.Frame()

        tk.Label(w, text = "Gib einen Spielernamen ein und drücke Start").pack()
        tk.Entry(w, bg='white', textvariable=self.nameInput).pack()

        w.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)

        w = tk.Frame()

        tk.Button(w, text="Start", command=self.startUp).pack()
        tk.Button(w, text="Stop", command=self.stop_thread).pack()
        tk.Button(w, text="Close", command=self.on_close).pack()

        w.pack(side=tk.RIGHT, fill=tk.BOTH, expand=0)
        self.f.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)

    def startUp(self):

        if (threading.active_count()!=0):

            self.my_thread = MyThread(self.queue,self.nameInput)
            self.my_thread.start()
            self.periodiccall()

    def stop_thread(self):

     if(threading.active_count()!=1):
         self.my_thread.stop()


    def periodiccall(self):

        self.checkqueue()
        if self.my_thread.is_alive():
            self.after(1, self.periodiccall)
        else:
            pass

    def checkqueue(self):
        while self.queue.qsize():
            try:
                ret = self.queue.get(0)
                msg = "%s"%(ret)
                print(msg)
            except queue.Empty:
                pass                    

    def on_close(self):
        if(threading.active_count()!=0):
            if self.my_thread is not None:
                self.my_thread.stop()

        self.master.destroy()

if __name__ == '__main__':
    app = App()
    app.mainloop()
0 голосов
/ 02 апреля 2019
def startUp():
    user_input()
    thr = threading.Thread(target=user_input)
    thr.start()

Это не выглядит правильно.Вы вызываете user_input() в основном потоке и дочернем потоке.Если вы хотите, чтобы он запускался только в дочернем потоке, не вызывайте его в первый раз.

def startUp():
    thr = threading.Thread(target=user_input)
    thr.start()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...