Reklam
Geliştirme aşamasındadır her özelliği çalışmazimport json
import os
import tkinter as tk
from tkinter import simpledialog, messagebox
from typing import List, Optional, Tuple, Any
import customtkinter
# Constants Deneme
class MarketMacro:
def __init__(self) -> None:
# Constants
self.PRICE_FILE = "fiyatlar.json"
self.NUM_PRODUCTS = 12
self.WINDOW_SIZE = "700x900"
# Initialize instance variables
self.window: Optional[customtkinter.CTk] = None
self.display_frame: Optional[customtkinter.CTkFrame] = None
self.checkboxes: List[tk.IntVar] = []
self.price_entries: List[customtkinter.CTkEntry] = []
self.quantity_entries: List[customtkinter.CTkEntry] = []
self.previous_quantities: List[str] = ["1"] * self.NUM_PRODUCTS
self.market_action = "Buy" # Default action
# self.select_all_var = tk.IntVar() # Remove this line from here
# Window setup
self.setup_window()
self.create_ui_elements()
self.load_prices()
def setup_window(self) -> None:
"""Initialize the main window with settings."""
customtkinter.set_appearance_mode("System")
customtkinter.set_default_color_theme("blue")
self.window = customtkinter.CTk()
self.window.title("Knight Online Market Macro")
self.window.geometry(self.WINDOW_SIZE)
self.window.resizable(True, True)
# Initialize select_all_var after the window is created
self.select_all_var = tk.IntVar()
# ... rest of your code remains unchanged ...
def create_ui_elements(self) -> None:
"""Create all UI elements."""
if not self.window:
raise RuntimeError("Window not initialized")
self.display_frame = customtkinter.CTkFrame(self.window)
self.display_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
# Create Buy and Sell buttons
self.create_buy_sell_buttons()
# Create product rows
self.create_product_rows()
# Create control buttons
self.create_control_buttons()
def create_buy_sell_buttons(self) -> None:
"""Create Buy and Sell buttons."""
if not self.window:
raise RuntimeError("Window not initialized")
customtkinter.CTkButton(
self.window,
text="Satın Al (Buy)",
command=self.set_all_buy_prices
).pack(pady=5, fill=tk.X)
customtkinter.CTkButton(
self.window,
text="Sat (Sell)",
command=self.set_all_sell_prices
).pack(pady=10, fill=tk.X)
def create_product_rows(self) -> None:
"""Create product rows with checkboxes, price fields, and quantity fields."""
if not self.display_frame:
raise RuntimeError("Display frame not initialized")
# Add a "Select All" checkbox
self.select_all_var = tk.IntVar()
select_all_checkbox = customtkinter.CTkCheckBox(
self.display_frame,
variable=self.select_all_var,
text="Tümünü Seç",
command=self.toggle_all_checkboxes
)
select_all_checkbox.pack(pady=5)
for i in range(self.NUM_PRODUCTS):
frame = customtkinter.CTkFrame(self.display_frame)
frame.pack(fill=tk.X, expand=True, pady=2)
# Checkbox for product
checkbox_var = tk.IntVar()
self.checkboxes.append(checkbox_var)
customtkinter.CTkCheckBox(
frame,
variable=checkbox_var,
text=f"Ürün {i + 1}"
).pack(side=tk.LEFT, padx=5)
# Checkbox for favorite
favorite_checkbox_var = tk.IntVar()
self.checkboxes.append(favorite_checkbox_var)
customtkinter.CTkCheckBox(
frame,
variable=favorite_checkbox_var,
text=f"Favori {i + 1}"
).pack(side=tk.RIGHT, padx=1)
# Quantity entry for product
quantity_entry = customtkinter.CTkEntry(frame, width=50)
quantity_entry.insert(0, "1")
quantity_entry.pack(side=tk.LEFT, padx=5)
self.quantity_entries.append(quantity_entry)
# Quantity entry for favorite
favorite_quantity_entry = customtkinter.CTkEntry(frame, width=50)
favorite_quantity_entry.insert(0, "1")
favorite_quantity_entry.pack(side=tk.RIGHT, padx=5)
self.quantity_entries.append(favorite_quantity_entry)
# Price entry
price_entry = customtkinter.CTkEntry(frame)
price_entry.pack(side=tk.RIGHT, padx=5, expand=True, fill=tk.X)
self.price_entries.append(price_entry)
# Restore button
restore_button = customtkinter.CTkButton(
frame,
text="⏪",
width=30,
command=lambda idx=i: self.restore_quantity(idx)
)
restore_button.pack(side=tk.RIGHT, padx=2)
# History button
customtkinter.CTkButton(
frame,
text="Son Fiyat Ve Adet",
command=lambda idx=i: self.copy_historical_price(idx)
).pack(side=tk.RIGHT, padx=1)
# Bind events
price_entry.bind('<FocusOut>', lambda e, idx=i: self.format_price(idx))
price_entry.bind('<KeyPress>', self.validate_key)
quantity_entry.bind('<KeyPress>', self.validate_quantity)
quantity_entry.bind('<FocusOut>', lambda e, idx=i: self.validate_and_set_quantity(idx))
self.add_copy_paste(price_entry)
def toggle_all_checkboxes(self) -> None:
"""Toggle all checkboxes based on the 'Select All' checkbox state."""
for var in self.checkboxes:
var.set(self.select_all_var.get())
def create_control_buttons(self) -> None:
"""Create control buttons."""
if not self.window:
raise RuntimeError("Window not initialized")
customtkinter.CTkButton(
self.window,
text="Temizle (Clear)",
command=self.clear_all
).pack(pady=10, fill=tk.X)
customtkinter.CTkButton(
self.window,
text="Pazarı Kur",
command=self.setup_market
).pack(pady=10, fill=tk.X)
def set_all_buy_prices(self) -> None:
"""Set all products to Buy prices."""
self.market_action = "Buy"
buy_price = simpledialog.askfloat("Buy Price", "Enter the Buy Price for all products:", minvalue=0.01)
if buy_price is not None:
self.set_all_prices("{:,.2f}".format(buy_price))
def set_all_sell_prices(self) -> None:
"""Set all products to Sell prices."""
self.market_action = "Sell"
sell_price = simpledialog.askfloat("Sell Price", "Enter the Sell Price for all products:", minvalue=0.01)
if sell_price is not None:
self.set_all_prices("{:,.2f}".format(sell_price))
def set_all_prices(self, price: str) -> None:
"""Set all price entries to the specified price."""
for entry in self.price_entries:
entry.delete(0, tk.END)
entry.insert(0, price)
def copy_historical_price(self, idx: int) -> None:
"""Copy historical price for the specified product."""
try:
if os.path.exists(self.PRICE_FILE):
with open(self.PRICE_FILE, 'r', encoding='utf-8') as file:
prices: List[List[float]] = json.load(file)
if idx < len(prices) and prices[idx]:
historical_price = prices[idx][-1]
self.price_entries[idx].delete(0, tk.END)
self.price_entries[idx].insert(0, "{:,.2f}".format(historical_price))
else:
messagebox.showwarning("Uyarı", f"Ürün {idx + 1} için geçmiş fiyat bulunamadı.")
except (json.JSONDecodeError, IOError) as e:
messagebox.showerror("Hata", f"Geçmiş fiyat kopyalanırken hata oluştu: {str(e)}")
def restore_quantity(self, index: int) -> None:
"""Restore previous quantity for a specific row."""
self.quantity_entries[index].delete(0, tk.END)
self.quantity_entries[index].insert(0, self.previous_quantities[index])
def validate_and_set_quantity(self, index: int) -> None:
"""Validate quantity and set default if invalid."""
quantity_entry = self.quantity_entries[index]
quantity_value = quantity_entry.get()
try:
quantity = int(quantity_value)
if quantity < 1 or quantity > 9999:
messagebox.showerror("Hata", "Geçersiz miktar! (1-9999 arası olmalı)")
quantity_entry.delete(0, tk.END)
quantity_entry.insert(0, "1")
except ValueError:
messagebox.showerror("Hata", "Geçersiz miktar! Lütfen bir sayı girin.")
quantity_entry.delete(0, tk.END)
quantity_entry.insert(0, "1")
def add_copy_paste(self, entry: customtkinter.CTkEntry) -> None:
"""Add copy/paste functionality to entry fields."""
entry.bind('<Control-c>', self.copy_to_clipboard)
entry.bind('<Control-v>', self.paste_from_clipboard)
entry.bind('<Control-a>', self.select_all)
@staticmethod
def copy_to_clipboard(event: tk.Event) -> None:
"""Copy selected text to clipboard."""
entry = event.widget
entry.clipboard_clear()
entry.clipboard_append(entry.get())
@staticmethod
def paste_from_clipboard(event: tk.Event) -> None:
"""Paste clipboard content with validation."""
entry = event.widget
try:
clipboard_content = entry.clipboard_get()
cleaned_content = clipboard_content.replace(',', '').strip()
try:
price_float = float(cleaned_content)
formatted_value = "{:,.2f}".format(price_float)
entry.delete(0, tk.END)
entry.insert(0, formatted_value)
except ValueError:
messagebox.showwarning("Uyarı", "Geçersiz fiyat formatı.")
except tk.TclError:
pass
return "break"
@staticmethod
def select_all(event: tk.Event) -> None:
"""Select all text in entry."""
event.widget.select_range(0, tk.END)
return "break"
@staticmethod
def validate_key(event: Any) -> Optional[str]:
"""Validate key input for price fields."""
if event.keysym in ('BackSpace', 'Delete', 'Left', 'Right', 'Tab'):
return None
if event.char.isdigit() or (event.char == '.' and '.' not in event.widget.get()):
return None
return "break"
@staticmethod
def validate_quantity(event: Any) -> Optional[str]:
"""Validate quantity input."""
if event.keysym in ('BackSpace', 'Delete', 'Left', 'Right', 'Tab'):
return None
if event.char.isdigit():
current_value = event.widget.get()
new_value = current_value + event.char
if new_value and (int(new_value) < 1 or int(new_value) > 9999):
return "break"
return None
return "break"
def format_price(self, index: int) -> None:
"""Format price with separators and decimals."""
entry = self.price_entries[index]
value = entry.get().replace(',', '')
try:
if value:
price_float = float(value)
formatted_value = "{:,.2f}".format(price_float)
entry.delete(0, tk.END)
entry.insert(0, formatted_value)
except ValueError:
entry.delete(0, tk.END)
def clear_all(self) -> None:
"""Clear all entries and save quantities."""
min_length = min(len(self.previous_quantities), len(self.quantity_entries))
for i in range(min_length):
self.previous_quantities[i] = self.quantity_entries[i].get()
self.quantity_entries[i].delete(0, tk.END)
self.quantity_entries[i].insert(0, "1")
for entry in self.price_entries:
entry.delete(0, tk.END)
print("clear_all function called!")
def setup_market(self) -> None:
"""Set up market with selected products."""
market_list: List[Tuple[str, float, str, int]] = []
for i in range(self.NUM_PRODUCTS):
if self.checkboxes[i].get():
price = self.price_entries[i].get().replace(',', '')
quantity = self.quantity_entries[i].get()
try:
if price:
price_float = float(price)
if quantity and 1 <= int(quantity) <= 9999:
market_list.append((f"Ürün {i + 1}", price_float, self.market_action, int(quantity)))
else:
messagebox.showerror("Hata", f"Ürün {i + 1} için geçersiz miktar. (1-9999 arası olmalı)")
return
else:
messagebox.showerror("Hata", f"Ürün {i + 1} için fiyat girilmedi.")
return
except ValueError:
messagebox.showerror("Hata", f"Ürün {i + 1} için geçersiz fiyat.")
return
if not market_list:
messagebox.showwarning("Uyarı", "Hiçbir ürün seçilmedi!")
return
buy_items = [f"{product}: {price:,.2f} Gold (Buy) - Miktar: {quantity}"
for product, price, action, quantity in market_list if action == "Buy"]
sell_items = [f"{product}: {price:,.2f} Gold (Sell) - Miktar: {quantity}"
for product, price, action, quantity in market_list if action == "Sell"]
message = "Pazara eklenen ürünler:\n"
if buy_items:
message += "\nAlınacak Ürünler:\n" + "\n".join(buy_items)
if sell_items:
message += "\nSatılacak Ürünler:\n" + "\n".join(sell_items)
messagebox.showinfo("Pazar Kuruldu", message)
self.save_prices()
def load_prices(self) -> None:
"""Load prices from file and populate the price entries."""
try:
if os.path.exists(self.PRICE_FILE):
with open(self.PRICE_FILE, 'r', encoding='utf-8') as file:
try:
prices: List[List[float]] = json.load(file)
except json.JSONDecodeError:
messagebox.showerror("Hata", "Fiyat dosyası bozuk. Varsayılan değerler kullanılıyor.")
prices = [] # Handle corrupted file
# Ensure prices list has enough entries
while len(prices) < self.NUM_PRODUCTS:
prices.append([])
for i in range(self.NUM_PRODUCTS):
if prices and i < len(prices) and prices[i]:
latest_price = prices[i][-1] # Use the latest price
self.price_entries[i].delete(0, tk.END)
self.price_entries[i].insert(0, "{:,.2f}".format(latest_price))
else:
# Create an empty prices file if it doesn't exist
with open(self.PRICE_FILE, 'w', encoding='utf-8') as file:
json.dump([[] for _ in range(self.NUM_PRODUCTS)], file)
messagebox.showinfo("Bilgi", "Yeni fiyat dosyası oluşturuldu.")
except Exception as e: # Catch other potential errors
messagebox.showerror("Hata", f"Fiyatlar yüklenirken hata oluştu: {str(e)}")
def save_prices(self) -> None:
"""Save prices to file."""
prices: List[List[float]] = []
for i in range(self.NUM_PRODUCTS):
try:
price_str = self.price_entries[i].get().replace(',', '')
if price_str: # Check for empty string
price = float(price_str)
# Ensure the prices list has enough sublists
while len(prices) <= i:
prices.append([])
prices[i].append(price) # Append the current price
except ValueError:
messagebox.showwarning("Uyarı", f"Ürün {i + 1} için geçersiz fiyat. Kaydedilmedi.")
try:
with open(self.PRICE_FILE, 'w', encoding='utf-8') as file:
json.dump(prices, file, indent=4) # Use indent for readability
except Exception as e:
messagebox.showerror("Hata", f"Fiyatlar kaydedilirken hata oluştu: {str(e)}")
if __name__ == "__main__":
app = MarketMacro()
app.window.mainloop()