Я использую Tkinter с Python 3.11 в Windows. < /p>
Следующая программа создает простое окно с меню. Пользователь нажимает на «Game -> Select Game Directory», после чего GAME_DIRECTORY_SELECTION () Функция призвана для пользователя выбрать каталог.
self.conf = Config(self.game_directory)
< /code>
, а затем конкретная конфигурация игрока читается здесь < /p>
self.player = Player(self.game_directory, self.player_id)
, потому что 'x' in utilx.dat был бы Player_id .
Однако, если каталог содержит несколько файлов игрока (скажем, util1.dat util3.dat и util7.dat , the Self.display Function_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_DSILE_DSILE_DAT и util7.dat ). Чтобы позволить игроку выбрать один. Это делается путем повторного использования окна для создания нового кадра, метки, списков с файлами игрока и кнопкой. Как только пользователь выбрал один файл игрока, этот кадр уничтожен, и файл конкретного игрока можно прочитать. < /P>
import tkinter as tk
from tkinter import Menu, Text, Label, Button, Listbox, StringVar, ttk
from tkinter import filedialog, messagebox
from tkinter import ttk
import os.path
import sys
import time
from pathlib import Path
#from inventory_view import InventoryViewer
from player import Player
from config import Config
class Game:
def __init__(self, root):
self.game_directory = None
self.filelist = None
self._selected_indices = ''
self.playerfile = None
self.conf = None
self.root = root
self.root.title("My Game Client")
self.create_main_window()
print('playerfile', self.playerfile) # (**)
def create_main_window(self):
# Create menu
self.menu = Menu(self.root)
self.root.config(menu=self.menu)
# Game menu
self.game_menu = Menu(self.menu, tearoff=0)
self.menu.add_cascade(label="Game", menu=self.game_menu)
self.game_menu.add_command(label="Select game directory", command=self.game_directory_selection)
self.game_menu.add_separator()
self.game_menu.add_command(label="Save game") # TO DO: add command
self.game_menu.add_command(label="Inventory viewer", command=self.inventory_view)
self.game_menu.add_command(label="Exit", command=self.root.quit)
def game_directory_selection(self):
""" Choose game directory, or quit."""
while True:
self.game_directory = tk.filedialog.askdirectory()
if not self.game_directory:
if tk.messagebox.askyesno(
icon='warning',
title="Game directory selection",
message="You haven't chosen a game directory. Do you want to quit?"):
sys.exit(0)
else:
p = Path(self.game_directory)
self.filelist = list(p.glob('util[0-9].dat'))
if not self.filelist:
tk.messagebox.showerror(
title='Directory error',
message='Player files not found in directory')
else:
# If there is more than one player file,
# display a selection dialog to choose one.
if len(self.filelist) > 1:
filelist_tmp = [f.name for f in self.filelist]
self.display_file_selection(filelist_tmp)
else:
self.playerfile = self.filelist[0]
# Extract player ID from filename
self.player_id = self.playerfile.stem[-1]
print('self.player_id', self.player_id)
break
# Disable the menu entry for selecting game directory
self.game_menu.entryconfigure('Select game directory', state=tk.DISABLED)
# Read configuration files into self.conf variable
self.conf = Config(self.game_directory)
# Read player files into self.player variable
self.player = Player(self.game_directory, self.player_id) # (*)
def choose_file(self):
self._selected_indices = self._listbox.curselection()
self.playerfile = self.filelist[self._selected_indices[0]]
# Extract player ID from filename
self.player_id = self.playerfile.stem[-1]
print('self.player_id in choose_file', self.player_id)
self.gameselectionframe.destroy()
def display_file_selection(self, filelist):
# Destroy the previous frame if it exists
# try:
# _gameselectionframe = self.root.nametowidget('gameselectionframe')
# if _gameselectionframe:
# _gameselectionframe.destroy()
# except KeyError:
# pass
self.gameselectionframe = ttk.Frame(self.root, padding=(2, 2, 2, 2), name='gameselectionframe')
self.gameselectionframe.pack()
display_label = ttk.Label(self.gameselectionframe, text="Several player files were found. Please choose one.", width=60)
display_label.pack()
pl = tk.StringVar(value=filelist)
self._listbox = tk.Listbox(self.gameselectionframe, listvariable=pl, height=6, width=20)
self._listbox.selection_set(0)
self._listbox.pack()
btn = ttk.Button(self.gameselectionframe, text='Select', command=self.choose_file)
btn.pack()
def inventory_view(self):
if self.playerfile:
self.player = Player(self.game_directory)
#self.viewer = InventoryView(self.player.planets, self.conf)
else:
tk.messagebox.showerror(
title='Player file error',
message='No player file selected. Please select a game directory first.')
if __name__ == "__main__":
root = tk.Tk()
game = Game(root)
root.mainloop()
< /code>
Проблема, которую я столкнулся, когда есть несколько файлов игроков (например, в примере с 3 -ю игровыми файлами), заключается в том, что < /p>
self.player = Player(self.game_directory, self.player_id) # (*)
< /code>
выполняется до того, как у пользователя будет возможность выбрать один файл игрока. Тогда self.player_id
не является , а файл не может быть должным образом прочитал. В этом случае мне нужно предотвратить продолжение программы, пока я не установил Self.Player_ID правильно.
Я попытался создать game_directory_selection () Использовать tk.toplevel window с grab_set () , чтобы «Salt» программа/Loopure, пока пользователь выбирает, но но но ищет. /> Я также пытался использовать quit () в начале display_file_selection () выйти из основного цикла, а затем Mainloop () в конце Display_file_selection () для резюме основной цикл. Они просто читают эти файлы на словарях для последующего использования. Что меня не беспокоит, потому что я не хочу ничего там печатать, это просто, чтобы проиллюстрировать тот факт, что Mainloop не ждал самостоятельно. wait_variable () Но они говорят, что обычное приложение GUI обычно не работает таким образом. Я также прочитал этот вопрос.
Заранее.
Я использую Tkinter с Python 3.11 в Windows. < /p> Следующая программа создает простое окно с меню. Пользователь нажимает на «Game -> Select Game Directory», после чего GAME_DIRECTORY_SELECTION () Функция призвана для пользователя выбрать каталог.[code]self.conf = Config(self.game_directory) < /code> , а затем конкретная конфигурация игрока читается здесь < /p> self.player = Player(self.game_directory, self.player_id) [/code] , потому что 'x' in utilx.dat был бы Player_id . Однако, если каталог содержит несколько файлов игрока (скажем, util1.dat util3.dat и util7.dat , the Self.display Function_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_FILE_DSILE_DSILE_DAT и util7.dat ). Чтобы позволить игроку выбрать один. Это делается путем повторного использования окна для создания нового кадра, метки, списков с файлами игрока и кнопкой. Как только пользователь выбрал один файл игрока, этот кадр уничтожен, и файл конкретного игрока можно прочитать. < /P> [code]import tkinter as tk from tkinter import Menu, Text, Label, Button, Listbox, StringVar, ttk from tkinter import filedialog, messagebox from tkinter import ttk import os.path import sys import time from pathlib import Path
#from inventory_view import InventoryViewer from player import Player from config import Config
self.root = root self.root.title("My Game Client")
self.create_main_window()
print('playerfile', self.playerfile) # (**)
def create_main_window(self): # Create menu self.menu = Menu(self.root) self.root.config(menu=self.menu)
# Game menu self.game_menu = Menu(self.menu, tearoff=0) self.menu.add_cascade(label="Game", menu=self.game_menu) self.game_menu.add_command(label="Select game directory", command=self.game_directory_selection) self.game_menu.add_separator() self.game_menu.add_command(label="Save game") # TO DO: add command self.game_menu.add_command(label="Inventory viewer", command=self.inventory_view) self.game_menu.add_command(label="Exit", command=self.root.quit)
def game_directory_selection(self): """ Choose game directory, or quit."""
while True: self.game_directory = tk.filedialog.askdirectory() if not self.game_directory: if tk.messagebox.askyesno( icon='warning', title="Game directory selection", message="You haven't chosen a game directory. Do you want to quit?"): sys.exit(0) else: p = Path(self.game_directory) self.filelist = list(p.glob('util[0-9].dat'))
if not self.filelist: tk.messagebox.showerror( title='Directory error', message='Player files not found in directory') else: # If there is more than one player file, # display a selection dialog to choose one. if len(self.filelist) > 1: filelist_tmp = [f.name for f in self.filelist] self.display_file_selection(filelist_tmp) else: self.playerfile = self.filelist[0] # Extract player ID from filename self.player_id = self.playerfile.stem[-1] print('self.player_id', self.player_id) break
# Disable the menu entry for selecting game directory self.game_menu.entryconfigure('Select game directory', state=tk.DISABLED)
# Read configuration files into self.conf variable self.conf = Config(self.game_directory)
# Read player files into self.player variable self.player = Player(self.game_directory, self.player_id) # (*)
# Extract player ID from filename self.player_id = self.playerfile.stem[-1] print('self.player_id in choose_file', self.player_id) self.gameselectionframe.destroy()
def display_file_selection(self, filelist):
# Destroy the previous frame if it exists # try: # _gameselectionframe = self.root.nametowidget('gameselectionframe') # if _gameselectionframe: # _gameselectionframe.destroy() # except KeyError: # pass
else: tk.messagebox.showerror( title='Player file error', message='No player file selected. Please select a game directory first.')
if __name__ == "__main__": root = tk.Tk() game = Game(root) root.mainloop() < /code> Проблема, которую я столкнулся, когда есть несколько файлов игроков (например, в примере с 3 -ю игровыми файлами), заключается в том, что < /p> self.player = Player(self.game_directory, self.player_id) # (*) < /code> выполняется до того, как у пользователя будет возможность выбрать один файл игрока. Тогда self.player_id [/code] не является , а файл не может быть должным образом прочитал. В этом случае мне нужно предотвратить продолжение программы, пока я не установил Self.Player_ID правильно. Я попытался создать game_directory_selection () Использовать tk.toplevel window с grab_set () , чтобы «Salt» программа/Loopure, пока пользователь выбирает, но но но ищет. /> Я также пытался использовать quit () в начале display_file_selection () выйти из основного цикла, а затем Mainloop () в конце Display_file_selection () для резюме основной цикл. Они просто читают эти файлы на словарях для последующего использования. Что меня не беспокоит, потому что я не хочу ничего там печатать, это просто, чтобы проиллюстрировать тот факт, что Mainloop не ждал самостоятельно. wait_variable () Но они говорят, что обычное приложение GUI обычно не работает таким образом. Я также прочитал этот вопрос. Заранее.
Это не дубликат Python tkinter mainloop, который не бросается в закрытие окна
У меня есть приложение, которое накапливается на Tkinter. Я наблюдал, что иногда после закрытия окна, используя кнопку x, код не будет выполнять линию MainLoop () . Это...
Я программирую на Python, и у меня есть несколько вопросов, на которые я нигде не могу найти ответ (пожалуйста, прочитайте все вопросы по мере их поступления до моего последнего вопроса):
Что на самом деле делает .mainloop()? Я прочитал все...
I understand how the function works itself, however, mainloop() is usually at the end of your code in modules like turtle and tkinter and you're required to put it at the end or there will be a syntax error and/or the remaining code is discarded...