Python / Tkinter: создайте повторно вызываемый фрейм внутри класса - PullRequest
0 голосов
/ 24 декабря 2018

Я пытаюсь создать пользовательский интерфейс с Tkinter и другим модулем под названием pandastable .Я вызываю пользовательский интерфейс через класс, потому что он поддерживает все мои подфункции активными, пока пользовательский интерфейс активен.

Вот где я застрял.В ходе выполнения этого кода необходимо воссоздать кадр данных Pandas на основе пользовательского ввода, а затем обновить интерфейс пользователя, чтобы отобразить новый кадр данных на экране.Следовательно, мне нужно обновить его с помощью класса, но я не могу понять, как заставить это работать.Вот весь код.Обновление происходит под функцией «refresh_df».

import pandas as pd
import numpy as np
from tkinter import *
from tkinter import ttk
from pandastable import Table, TableModel

#Create the frame class and call my functions from inside the class

class UserInterface(Table):
    # Launch the df in a pandastable frame

    def handleCellEntry(self, row, col):
        super().handleCellEntry(row, col)
        print('changed:', row, col, "(TODO: update database)")
        return

    def refresh_df(self, df):
        Frame.__init__(self)
        f = Frame(mainframe)
        f.grid(column=0, row=1, sticky=(E, W))
        screen_width = f.winfo_screenwidth() * 0.8
        screen_height = f.winfo_screenheight() * 0.7
        self.table = pt = Table(f, dataframe=df, height = screen_height, width = screen_width)
        pt.show()
        return

    def change_df(self, input_val):
        #Responds to button
        ui_df['Test col'] = input_val
        self.refresh_df(df=ui_df)

    def change_df_combo(self, event):
        #Responds to combobox, supposed to filter by 'Sec_type'
        combo_selection = str(combo_box.get())
        ui_df = pos_df[pos_df['Sec_type'] == combo_selection]
        ui_df['Test col combo'] = combo_selection
        self.refresh_df(df=ui_df)

pos_data = {'Location' : ['Denver', 'Boulder', 'Phoenix', 'Reno', 'Portland',
    'Eugene', 'San Francisco'], 'Sec_type' : ['mbus', 'mbus', 'vmus', 'caus',
    'vmus', 'mbus', 'mbus'], 'Rando_num': [18, 5, 34, 11, 72, 42, 9]}
pos_df = pd.DataFrame(data = pos_data)

ui_df = pos_df

#Launch Tkinter basics
root = Tk()
root.title("S test...")

mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)

f = Frame(mainframe)
f.grid(column=0, row=1, sticky=(E, W))
screen_width = f.winfo_screenwidth() * 0.8
screen_height = f.winfo_screenheight() * 0.7

ui = UserInterface(f, dataframe=pos_df, height = screen_height, width = screen_width)

#'Test' button, adds a column
col_val_input = 'It worked!'
test_button = ttk.Button(mainframe, text = 'Test', command= lambda: ui.change_df(input_val=col_val_input))
test_button.grid(column=0, row=0, sticky=(W))

#Combobox to filter df
combo_choices = ['mbus', 'vmus', 'caus']
choice = StringVar()
combo_box = ttk.Combobox(mainframe, textvariable=choice)
combo_box['values'] = combo_choices
combo_box.grid(column=1, row=0, sticky=(W))
combo_box.bind('<<ComboboxSelected>>', ui.change_df_combo)

ui.show()

root.mainloop()

Ключ состоит из следующих двух строк:

        self.table = pt = Table(f, dataframe=df, height = screen_height, width = screen_width)
        pt.show()

Они просто отлично вызывают фрейм данных, но не делают этого извнутри класса, так что я не получаю всю функциональность.Мне казалось, что что-то вроде этого должно работать:

self.table = Table(f, dataframe=df, height = screen_height, width = screen_width)
self.show()

Но это не так.Опять же, я использую здесь pandastable, но думаю, что основная проблема в том, что я не использую правильную номенклатуру в классе, чтобы все это работало.Есть идеи?

1 Ответ

0 голосов
/ 26 декабря 2018

Хорошо, пандастабильные ботаники ... Я думаю, что это правильный способ справиться с этим(показывает только класс).Ключ в том, чтобы использовать функциональность updateModel / TableModel.

Я использую его, меняя свой DataFrame, а затем обновляя TableModel, но IIUC TableModel, по сути, имеет свою собственную df, так что вы можете обновить это непосредственно сo влияние на оригинальную df, если это полезно для вас.В любом случае, моя проблема с исходным кодом заключалась в том, что я эффективно создавал новый df после запуска события ComboBox, и поэтому pandastable не знал, что с этим делать.Вы можете манипулировать DataFrame и просто вызывать «redraw ()», и это прекрасно работает, но если вы восстанавливаете df, он ломается.

Вот код:

import pandas as pd
import numpy as np
from tkinter import *
from tkinter import ttk
from pandastable import Table, TableModel

#Create the frame class and call my functions from inside the class

class UserInterface(Table):
    # Launch the df in a pandastable frame

    def handleCellEntry(self, row, col):
        super().handleCellEntry(row, col)
        print('changed:', row, col, "(TODO: update database)")
        return    

    def change_df(self, input_val):
        #Responds to button
        ui_df['Test col'] = input_val
        self.updateModel(TableModel(ui_df))
        self.redraw()

    def change_df_combo(self, event):
        #Responds to combobox, filter by 'Sec_type'
        combo_selection = str(combo_box.get())
        ui_df = pos_df[pos_df['Sec_type'] == combo_selection]
        ui_df['Test col combo'] = combo_selection
        self.updateModel(TableModel(ui_df))
        self.redraw()

pos_data = {'Location' : ['Denver', 'Boulder', 'Phoenix', 'Reno', 'Portland',
    'Eugene', 'San Francisco'], 'Sec_type' : ['mbus', 'mbus', 'vmus', 'caus',
    'vmus', 'mbus', 'mbus'], 'Rando_num': [18, 5, 34, 11, 72, 42, 9]}
pos_df = pd.DataFrame(data = pos_data)

ui_df = pos_df

#Launch Tkinter basics
root = Tk()
root.title("S test...")

mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)

f = Frame(mainframe)
f.grid(column=0, row=1, sticky=(E, W))
screen_width = f.winfo_screenwidth() * 0.8
screen_height = f.winfo_screenheight() * 0.7

ui = UserInterface(f, dataframe=pos_df, height = screen_height, width = screen_width)

#'Test' button, adds a column
col_val_input = 'It worked!'
test_button = ttk.Button(mainframe, text = 'Test', command= lambda: ui.change_df(input_val=col_val_input))
test_button.grid(column=0, row=0, sticky=(W))

#Combobox to filter df
combo_choices = ['mbus', 'vmus', 'caus']
choice = StringVar()
combo_box = ttk.Combobox(mainframe, textvariable=choice)
combo_box['values'] = combo_choices
combo_box.grid(column=1, row=0, sticky=(W))
combo_box.bind('<<ComboboxSelected>>', ui.change_df_combo)

ui.show()

root.mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...