复制代码

程序设计 计算器 拼图 编辑器

计算器

import tkinter as tk
from tkinter import messagebox
from math import sqrt

class CalcApp:
    def __init__(self, root):
        self.root = root
        self.root.title("综合计算器")

        self.mode = tk.StringVar(value="普通计算器")
        self.create_menu()

        self.norm_frame = tk.Frame(self.root)
        self.mort_frame = tk.Frame(self.root)

        self.create_norm_calc(self.norm_frame)
        self.create_mort_calc(self.mort_frame)

        self.norm_frame.grid(row=1, column=0, sticky="nsew")
        self.mort_frame.grid(row=1, column=0, sticky="nsew")

        self.root.grid_rowconfigure(1, weight=1)
        self.root.grid_columnconfigure(0, weight=1)

        self.expr = ""

    def create_menu(self):
        modes = ["普通计算器", "贷款计算器"]
        tk.OptionMenu(self.root, self.mode, *modes, command=self.switch_mode).grid(row=0, column=0, padx=10, pady=10)

    def switch_mode(self, mode):
        if mode == "普通计算器":
            self.mort_frame.grid_forget()
            self.norm_frame.grid(row=1, column=0, padx=10, pady=10)
        else:
            self.norm_frame.grid_forget()
            self.mort_frame.grid(row=1, column=0, padx=10, pady=10)

    def create_norm_calc(self, frame):
        self.res = tk.StringVar()

        self.display = tk.Text(frame, height=2, font=('Arial', 20), bd=10, wrap=tk.WORD)
        self.display.grid(row=0, column=0, columnspan=4, padx=10, pady=10, sticky="nsew")

        btns = [
            ('7', 1, 0), ('8', 1, 1), ('9', 1, 2), ('/', 1, 3),
            ('4', 2, 0), ('5', 2, 1), ('6', 2, 2), ('*', 2, 3),
            ('1', 3, 0), ('2', 3, 1), ('3', 3, 2), ('-', 3, 3),
            ('0', 4, 0), ('.', 4, 1), ('+', 4, 2), ('=', 4, 3),
            ('C', 5, 0), ('←', 5, 1), ('sqrt', 5, 2), ('%', 5, 3),
            ('(', 6, 0), (')', 6, 1), ('^', 6, 2), ('1/x', 6, 3)
        ]

        for (text, row, col) in btns:
            btn = tk.Button(frame, text=text, padx=20, pady=20, font=('Arial', 18),
                            command=lambda t=text: self.on_btn_click(t))
            btn.grid(row=row, column=col, sticky="nsew")

        for i in range(7):
            frame.grid_rowconfigure(i, weight=1)
        for i in range(4):
            frame.grid_columnconfigure(i, weight=1)

    def tokenize(self, expr):
        tokens = []
        current_num = []
        i = 0
        while i < len(expr):
            char = expr[i]
            if char.isdigit() or char == '.':
                current_num.append(char)
            else:
                if current_num:
                    tokens.append(''.join(current_num))
                    current_num = []
                if char in '+-*/^()':
                    tokens.append(char)
                elif char == 's' and expr[i:i + 4] == 'sqrt':
                    tokens.append('sqrt')
                    i += 3
                elif char == '1' and i + 1 < len(expr) and expr[i + 1] == '/':
                    tokens.append('1/x')
                    i += 1
                elif char == '%':
                    tokens.append('%')
            i += 1
        if current_num:
            tokens.append(''.join(current_num))
        return tokens

    def precedence(self, op) :
        if op == 'sqrt':
            return 4
        if op in ('+', '-'):
            return 1
        if op in ('*', '/', '%'):
            return 2
        if op == '^':
            return 3
        return 0

    def apply_op(self, a, b, op):
        if op == '+':
            return a + b
        if op == '-':
            return a - b
        if op == '*':
            return a * b
        if op == '/':
            return a / b
        if op == '^':
            return a ** b
        if op == '%':
            return a % b
        if op == '1/x':
            return 1 / b

    def perform_op(self):
        operator = self.op_stack.pop()
        if operator == 'sqrt':
            val = self.num_stack.pop()
            self.num_stack.append(sqrt(val))
        elif operator == '1/x':
            val = self.num_stack.pop()
            self.num_stack.append(1 / val)
        else:
            right = self.num_stack.pop()
            left = self.num_stack.pop()
            self.num_stack.append(self.apply_op(left, right, operator))

    def evaluate(self):
        self.num_stack = []
        self.op_stack = []
        tokens = self.tokenize(self.expr)

        for token in tokens:
            if token.isdigit() or '.' in token:
                self.num_stack.append(float(token))
            elif token in '+-*/^%':
                while (self.op_stack and self.precedence(self.op_stack[-1]) >= self.precedence(token)):
                    self.perform_op()
                self.op_stack.append(token)
            elif token == '(':
                self.op_stack.append(token)
            elif token == ')':
                while self.op_stack and self.op_stack[-1] != '(':
                    self.perform_op()
                self.op_stack.pop()  # 弹出'('
            elif token == 'sqrt':
                self.op_stack.append('sqrt')
            elif token == '1/x':
                self.op_stack.append('1/x')

        while self.op_stack:
            self.perform_op()
        self.expr = str(self.num_stack.pop())

    def on_btn_click(self, char):
        if char == '=':
            try:
                self.evaluate()
            except Exception:
                self.expr = "Error"
        elif char == 'C':
            self.expr = ""
        elif char == '←':
            self.expr = self.expr[:-1]
        else:
            self.expr += str(char)

        self.display.delete('1.0', tk.END)
        self.display.insert(tk.END, self.expr)

    def create_mort_calc(self, frame):
        self.pay_type = tk.StringVar(value="等额本息")
        self.years = tk.StringVar()
        self.amount = tk.StringVar()
        self.rate = tk.StringVar()
        self.monthly_pay = tk.StringVar()
        self.total_int = tk.StringVar()
        self.total_pay = tk.StringVar()

        tk.Label(frame, text="还款方式:").grid(row=0, column=0, padx=5, pady=5, sticky='w')
        tk.Radiobutton(frame, text="等额本息", variable=self.pay_type, value="等额本息").grid(row=0, column=1)
        tk.Radiobutton(frame, text="等额本金", variable=self.pay_type, value="等额本金").grid(row=0, column=2)

        tk.Label(frame, text="贷款年限(年):").grid(row=1, column=0, padx=5, pady=5, sticky='w')
        tk.Entry(frame, textvariable=self.years).grid(row=1, column=1, columnspan=2)

        tk.Label(frame, text="贷款金额(万元):").grid(row=2, column=0, padx=5, pady=5, sticky='w')
        tk.Entry(frame, textvariable=self.amount).grid(row=2, column=1, columnspan=2)

        tk.Label(frame, text="贷款利率(%):").grid(row=3, column=0, padx=5, pady=5, sticky='w')
        tk.Entry(frame, textvariable=self.rate).grid(row=3, column=1, columnspan=2)

        tk.Button(frame, text="计算", command=self.calc_mort).grid(row=4, column=0, columnspan=2, pady=10)
        tk.Button(frame, text="重置", command=self.reset_mort).grid(row=4, column=2, pady=10)

        tk.Label(frame, text="月均还款(元):").grid(row=5, column=0, padx=5, pady=5, sticky='w')
        tk.Entry(frame, textvariable=self.monthly_pay, state='readonly').grid(row=5, column=1, columnspan=2)

        tk.Label(frame, text="利息总额(元):").grid(row=6, column=0, padx=5, pady=5, sticky='w')
        tk.Entry(frame, textvariable=self.total_int, state='readonly').grid(row=6, column=1, columnspan=2)

        tk.Label(frame, text="还款总额(元):").grid(row=7, column=0, padx=5, pady=5, sticky='w')
        tk.Entry(frame, textvariable=self.total_pay, state='readonly').grid(row=7, column=1, columnspan=2)

    def calc_mort(self):
        """贷款计算器计算逻辑"""
        try:
            yrs = int(self.years.get())
            princ = float(self.amount.get()) * 10000  # 万元转换为元
            rate_yr = float(self.rate.get()) / 100  # 转换为小数利率
            months = yrs * 12  # 贷款总月数
            rate_mth = rate_yr / 12  # 月利率

            if self.pay_type.get() == "等额本息":
                # 等额本息公式
                m_pay = princ * rate_mth * ((1 + rate_mth) ** months) / (((1 + rate_mth) ** months) - 1)
                total_pay = m_pay * months
                total_int = total_pay - princ
            else:
                # 等额本金公式
                m_pay = princ / months + (princ * rate_mth)
                total_pay = (months + 1) * princ * rate_mth / 2 + princ
                total_int = total_pay - princ

            self.monthly_pay.set(f"{m_pay:.2f}")
            self.total_int.set(f"{total_int:.2f}")
            self.total_pay.set(f"{total_pay:.2f}")

        except ValueError:
            messagebox.showerror("输入错误", "请输入有效的数字")

    def reset_mort(self):
        """重置贷款计算器输入和输出"""
        self.years.set("")
        self.amount.set("")
        self.rate.set("")
        self.monthly_pay.set("")
        self.total_int.set("")
        self.total_pay.set("")

if __name__ == "__main__":
    root = tk.Tk()
    app = CalcApp(root)
    root.mainloop()

拼图

import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk
import random

class MyPuzzleGame:
    def __init__(self, root):
        self.root = root
        self.root.title("拼图游戏")

        self.grid_size = 3  # Default grid size
        self.tile_size = 150  # Size of each tile
        self.image_path = None
        self.original_image = None
        self.tiles = {}  # Stores tiles for each grid size
        self.correct_positions = []
        self.current_positions = []
        self.selected_tile = None
        self.time_remaining = 0
        self.timer_label = None
        self.timer_id = None
        self.manual_check = False  # Track manual "Check Puzzle" clicks

        self.setup_ui()

    def setup_ui(self):
        self.canvas = tk.Canvas(self.root, width=450, height=450, bg="white")
        self.canvas.grid(row=0, column=0, columnspan=5)

        tk.Button(self.root, text="加载图片", command=self.load_image).grid(row=1, column=0)
        tk.Button(self.root, text="重置拼图", command=self.reset_puzzle).grid(row=1, column=1)
        tk.Button(self.root, text="查看原图", command=self.show_original_image).grid(row=1, column=2)
        tk.Button(self.root, text="检查拼图", command=self.check_puzzle).grid(row=1, column=3)

        self.timer_label = tk.Label(self.root, text="倒计时: 00:00")
        self.timer_label.grid(row=1, column=4)
        self.time_var = tk.StringVar(self.root)
        self.time_var.set("30s")
        tk.OptionMenu(self.root, self.time_var, "30s", "1min", "3min", "5min", command=self.set_timer).grid(row=2, column=4)

        # Difficulty selection
        tk.Button(self.root, text="3x3", command=lambda: self.change_difficulty(3)).grid(row=2, column=0)
        tk.Button(self.root, text="4x4", command=lambda: self.change_difficulty(4)).grid(row=2, column=1)
        tk.Button(self.root, text="5x5", command=lambda: self.change_difficulty(5)).grid(row=2, column=2)

    def change_difficulty(self, size):
        self.grid_size = size
        self.tile_size = 450 // size  # Adjust tile size according to grid size
        self.reset_puzzle()

    def set_timer(self, _=None):
        if self.timer_id:
            self.root.after_cancel(self.timer_id)
        times = {"30s": 30, "1min": 60, "3min": 180, "5min": 300}
        self.time_remaining = times[self.time_var.get()]
        self.update_timer()

    def update_timer(self):
        mins, secs = divmod(self.time_remaining, 60)
        self.timer_label.config(text=f"倒计时: {mins:02d}:{secs:02d}")

        if self.time_remaining > 0:
            self.time_remaining -= 1
            self.timer_id = self.root.after(1000, self.update_timer)
        else:
            messagebox.showinfo("时间到", "很遗憾,您没有在规定时间内完成拼图。")
            self.reset_puzzle()

    def load_image(self):
        self.image_path = filedialog.askopenfilename(title="选择图片",
                                                     filetypes=[("Image Files", "*.png;*.jpg;*.jpeg")])
        if not self.image_path:
            return
        self.original_image = Image.open(self.image_path).resize((450, 450))
        self.setup_tiles()
        self.display_tiles()

    def setup_tiles(self):
        self.tiles[self.grid_size] = []
        self.correct_positions = []
        self.current_positions = []

        for i in range(self.grid_size):
            row = []
            for j in range(self.grid_size):
                x, y = j * self.tile_size, i * self.tile_size
                crop = self.original_image.crop((x, y, x + self.tile_size, y + self.tile_size))
                photo = ImageTk.PhotoImage(crop)
                row.append(photo)
                self.correct_positions.append((i, j))
            self.tiles[self.grid_size].append(row)

        self.current_positions = self.correct_positions[:]
        random.shuffle(self.current_positions)

    def display_tiles(self):
        self.canvas.delete("all")
        for idx, pos in enumerate(self.current_positions):
            x, y = pos[1] * self.tile_size, pos[0] * self.tile_size
            self.canvas.create_image(x, y, image=self.tiles[self.grid_size][self.correct_positions[idx][0]][
                self.correct_positions[idx][1]], anchor=tk.NW, tags=f"tile{idx}")
        self.canvas.bind("<Button-1>", self.on_tile_press)
        self.canvas.bind("<B1-Motion>", self.on_tile_drag)
        self.canvas.bind("<ButtonRelease-1>", self.on_tile_release)

    def on_tile_press(self, event):
        x, y = event.x, event.y
        for idx, pos in enumerate(self.current_positions):
            tile_x, tile_y = pos[1] * self.tile_size, pos[0] * self.tile_size
            if tile_x <= x < tile_x + self.tile_size and tile_y <= y < tile_y + self.tile_size:
                self.selected_tile = idx
                self.offset_x, self.offset_y = x - tile_x, y - tile_y
                break

    def on_tile_drag(self, event):
        if self.selected_tile is not None:
            x, y = event.x - self.offset_x, event.y - self.offset_y
            self.canvas.coords(f"tile{self.selected_tile}", x, y)

    def on_tile_release(self, event):
        if self.selected_tile is not None:
            target_pos = self.correct_positions[self.selected_tile]
            closest_idx = self.find_closest_tile(event.x, event.y)
            if closest_idx is not None:
                # Swap positions in current_positions
                self.current_positions[self.selected_tile], self.current_positions[closest_idx] = \
                    self.current_positions[closest_idx], self.current_positions[self.selected_tile]
            self.display_tiles()  # Re-display tiles to reset positions after release

            if self.is_puzzle_complete():
                messagebox.showinfo("成功", "您完成了拼图!")
            self.selected_tile = None

    def find_closest_tile(self, x, y):
        for idx, pos in enumerate(self.current_positions):
            tile_x, tile_y = pos[1] * self.tile_size + self.tile_size // 2, pos[0] * self.tile_size + self.tile_size // 2
            if abs(tile_x - x) < self.tile_size // 2 and abs(tile_y - y) < self.tile_size // 2:
                return idx
        return None

    def reset_puzzle(self):
        if self.timer_id:
            self.root.after_cancel(self.timer_id)
        self.setup_tiles()
        self.display_tiles()
        self.set_timer()

    def show_original_image(self):
        if self.original_image:
            top = tk.Toplevel(self.root)
            top.title("原图")
            img = ImageTk.PhotoImage(self.original_image)
            img_label = tk.Label(top, image=img)
            img_label.image = img  # Keep reference to avoid garbage-collection
            img_label.pack()

    def check_puzzle(self):
        self.manual_check = True  # Mark that "Check Puzzle" was clicked
        if self.is_puzzle_complete():
            messagebox.showinfo("成功", "您完成了拼图!")
        elif self.manual_check:
            messagebox.showinfo("未完成", "拼图未完成,请继续努力。")
            self.manual_check = False

    def is_puzzle_complete(self):
        return self.current_positions == self.correct_positions

if __name__ == "__main__":
    root = tk.Tk()
    game = MyPuzzleGame(root)
    root.mainloop()

多文本编辑器

import tkinter as tk
from tkinter import filedialog, font, simpledialog, messagebox, ttk
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas


class SimpleMDIExample:
    def __init__(self, root):
        self.root = root
        self.root.title('Simple Multi-Tab Editor')

        # Notebook for tabs
        self.notebook = ttk.Notebook(root)
        self.notebook.pack(fill=tk.BOTH, expand=True)

        # Initialize menu and add the first tab
        self.current_language = "English"
        self.languages = self.load_languages()
        self.font_options = ["Microsoft YaHei", "Arial", "Times New Roman", "Courier New"]
        self.size_options = [10, 12, 14, 16, 18, 20]
        self.file_paths = {}  # Dictionary to store file path for each tab

        self.load_menu()
        self.add_tab()

    def load_languages(self):
        return {
            "English": {
                "file": "File",
                "new": "New",
                "open": "Open",
                "save": "Save",
                "edit": "Edit",
                "undo": "Undo",
                "redo": "Redo",
                "cut": "Cut",
                "copy": "Copy",
                "paste": "Paste",
                "find": "Find",
                "replace": "Replace",
                "format": "Format",
                "font": "Font",
                "font_size": "Font Size",
                "bold": "Bold",
                "italic": "Italic",
                "underline": "Underline",
                "align": "Align",
                "align_left": "Left Align",
                "align_center": "Center Align",
                "align_right": "Right Align",
                "settings": "Settings",
                "language": "Language",
                "export_pdf": "Export as PDF",
                "exit": "Exit"
            },
            "中文": {
                "file": "文件",
                "new": "新建",
                "open": "打开",
                "save": "保存",
                "edit": "编辑",
                "undo": "撤销",
                "redo": "重做",
                "cut": "剪切",
                "copy": "复制",
                "paste": "粘贴",
                "find": "查找",
                "replace": "替换",
                "format": "格式",
                "font": "字体",
                "font_size": "字体大小",
                "bold": "加粗",
                "italic": "斜体",
                "underline": "下划线",
                "align": "对齐",
                "align_left": "左对齐",
                "align_center": "居中对齐",
                "align_right": "右对齐",
                "settings": "设置",
                "language": "语言",
                "export_pdf": "导出为PDF",
                "exit": "退出"
            }
        }

    def load_menu(self):
        menu = tk.Menu(self.root)
        self.root.config(menu=menu)

        file_menu = tk.Menu(menu, tearoff=0)
        menu.add_cascade(label=self.languages[self.current_language]["file"], menu=file_menu)
        file_menu.add_command(label=self.languages[self.current_language]["new"], command=self.add_tab)
        file_menu.add_command(label=self.languages[self.current_language]["open"], command=self.open_file)
        file_menu.add_command(label=self.languages[self.current_language]["save"], command=self.save_file)
        file_menu.add_command(label=self.languages[self.current_language]["export_pdf"], command=self.export_as_pdf)

        edit_menu = tk.Menu(menu, tearoff=0)
        menu.add_cascade(label=self.languages[self.current_language]["edit"], menu=edit_menu)
        edit_menu.add_command(label=self.languages[self.current_language]["undo"],
                              command=lambda: self.get_current_text_widget().event_generate('<<Undo>>'))
        edit_menu.add_command(label=self.languages[self.current_language]["redo"],
                              command=lambda: self.get_current_text_widget().event_generate('<<Redo>>'))
        edit_menu.add_separator()
        edit_menu.add_command(label=self.languages[self.current_language]["cut"],
                              command=lambda: self.get_current_text_widget().event_generate('<<Cut>>'))
        edit_menu.add_command(label=self.languages[self.current_language]["copy"],
                              command=lambda: self.get_current_text_widget().event_generate('<<Copy>>'))
        edit_menu.add_command(label=self.languages[self.current_language]["paste"],
                              command=lambda: self.get_current_text_widget().event_generate('<<Paste>>'))
        edit_menu.add_command(label=self.languages[self.current_language]["find"], command=self.find_text)
        edit_menu.add_command(label=self.languages[self.current_language]["replace"], command=self.replace_text)

        format_menu = tk.Menu(menu, tearoff=0)
        menu.add_cascade(label=self.languages[self.current_language]["format"], menu=format_menu)
        format_menu.add_command(label=self.languages[self.current_language]["font"], command=self.select_font)
        format_menu.add_command(label=self.languages[self.current_language]["font_size"], command=self.select_font_size)
        format_menu.add_command(label=self.languages[self.current_language]["bold"], command=self.set_bold)
        format_menu.add_command(label=self.languages[self.current_language]["italic"], command=self.set_italic)
        format_menu.add_command(label=self.languages[self.current_language]["underline"], command=self.set_underline)

        align_menu = tk.Menu(format_menu, tearoff=0)
        format_menu.add_cascade(label=self.languages[self.current_language]["align"], menu=align_menu)
        align_menu.add_command(label=self.languages[self.current_language]["align_left"], command=lambda: self.set_alignment("left"))
        align_menu.add_command(label=self.languages[self.current_language]["align_center"], command=lambda: self.set_alignment("center"))
        align_menu.add_command(label=self.languages[self.current_language]["align_right"], command=lambda: self.set_alignment("right"))

        settings_menu = tk.Menu(menu, tearoff=0)
        menu.add_cascade(label=self.languages[self.current_language]["settings"], menu=settings_menu)
        language_menu = tk.Menu(settings_menu, tearoff=0)
        settings_menu.add_cascade(label=self.languages[self.current_language]["language"], menu=language_menu)
        language_menu.add_command(label="English", command=lambda: self.switch_language("English"))
        language_menu.add_command(label="中文", command=lambda: self.switch_language("中文"))
        settings_menu.add_command(label=self.languages[self.current_language]["exit"], command=self.root.quit)

    def switch_language(self, language):
        self.current_language = language
        self.load_menu()

    def add_tab(self, title="Untitled"):
        frame = ttk.Frame(self.notebook)
        frame.pack(fill=tk.BOTH, expand=True)

        text_area = tk.Text(frame, wrap=tk.WORD, undo=True, font=("Microsoft YaHei", 12))
        text_area.pack(fill=tk.BOTH, expand=True)

        text_area.tag_configure("left", justify="left")
        text_area.tag_configure("center", justify="center")
        text_area.tag_configure("right", justify="right")

        # Add a close button to the tab title
        tab_id = self.notebook.tabs()[-1] if self.notebook.tabs() else 0
        title_with_close = f"{title}  ✕"
        self.notebook.add(frame, text=title_with_close)
        self.notebook.select(frame)

        # Add close functionality
        self.file_paths[frame] = None
        self.notebook.bind("<ButtonRelease-1>", self.on_close_click)

    def on_close_click(self, event):
        x, y = event.x, event.y
        current_index = self.notebook.index("@%d,%d" % (x, y))
        tab_text = self.notebook.tab(current_index, "text")

        # Check if the click was on the close button part (✕)
        if "✕" in tab_text and x > self.notebook.bbox(current_index)[2] - 20:
            frame = self.notebook.nametowidget(self.notebook.tabs()[current_index])
            del self.file_paths[frame]
            self.notebook.forget(current_index)

    def get_current_text_widget(self):
        current_tab = self.notebook.select()
        current_frame = self.notebook.nametowidget(current_tab)
        text_widget = current_frame.winfo_children()[0]
        return text_widget

    def set_alignment(self, alignment):
        text_widget = self.get_current_text_widget()
        selected_text = text_widget.tag_ranges("sel")
        if selected_text:
            text_widget.tag_remove("left", "1.0", tk.END)
            text_widget.tag_remove("center", "1.0", tk.END)
            text_widget.tag_remove("right", "1.0", tk.END)
            text_widget.tag_add(alignment, "sel.first", "sel.last")
        else:
            messagebox.showwarning("Warning", "No text selected!")

    def open_file(self):
        file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt")])
        if file_path:
            self.add_tab(title=file_path.split('/')[-1])
            text_widget = self.get_current_text_widget()
            with open(file_path, 'r', encoding='utf-8') as file:
                content = file.read()
            text_widget.insert("1.0", content)

            current_tab = self.notebook.select()
            self.file_paths[self.notebook.nametowidget(current_tab)] = file_path

    def save_file(self):
        current_tab = self.notebook.select()
        text_widget = self.get_current_text_widget()
        content = text_widget.get("1.0", tk.END).strip()
        file_path = self.file_paths[self.notebook.nametowidget(current_tab)]

        if not file_path:
            file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files", "*.txt")])
            if not file_path:
                return

            self.file_paths[self.notebook.nametowidget(current_tab)] = file_path
            self.notebook.tab(current_tab, text=file_path.split('/')[-1])

        with open(file_path, 'w', encoding='utf-8') as file:
            file.write(content)

    def export_as_pdf(self):
        text_widget = self.get_current_text_widget()
        content = text_widget.get("1.0", tk.END).strip()
        file_path = filedialog.asksaveasfilename(filetypes=[("PDF files", "*.pdf")])
        if file_path:
            if not file_path.endswith('.pdf'):
                file_path += '.pdf'
            self.save_text_as_pdf(file_path, content)

    def save_text_as_pdf(self, file_path, text):
        c = canvas.Canvas(file_path, pagesize=letter)
        text = text.split('\n')
        text_height = 750
        for line in text:
            c.drawString(72, text_height, line)
            text_height -= 12
        c.save()

    def select_font(self):
        font_selection = simpledialog.askstring("Select Font", "Choose a font:\n" + "\n".join(self.font_options))
        if font_selection in self.font_options:
            text_widget = self.get_current_text_widget()
            selected_range = text_widget.tag_ranges("sel")
            if selected_range:
                text_widget.tag_configure("custom_font", font=(font_selection, 12))
                text_widget.tag_add("custom_font", selected_range[0], selected_range[1])
            else:
                messagebox.showwarning("Warning", "No text selected!")

    def select_font_size(self):
        size_selection = simpledialog.askstring("Select Font Size",
                                                "Choose a size:\n" + ", ".join(map(str, self.size_options)))
        if size_selection.isdigit() and int(size_selection) in self.size_options:
            text_widget = self.get_current_text_widget()
            selected_range = text_widget.tag_ranges("sel")
            if selected_range:
                text_widget.tag_configure("custom_size", font=("Microsoft YaHei", int(size_selection)))
                text_widget.tag_add("custom_size", selected_range[0], selected_range[1])
            else:
                messagebox.showwarning("Warning", "No text selected!")

    def set_bold(self):
        text_widget = self.get_current_text_widget()
        bold_font = font.Font(text_widget, text_widget.cget("font"))
        bold_font.config(weight="bold")
        text_widget.tag_configure("bold", font=bold_font)
        try:
            text_widget.tag_add("bold", "sel.first", "sel.last")
        except tk.TclError:
            messagebox.showwarning("Warning", "No text selected!")

    def set_italic(self):
        text_widget = self.get_current_text_widget()
        italic_font = font.Font(text_widget, text_widget.cget("font"))
        italic_font.config(slant="italic")
        text_widget.tag_configure("italic", font=italic_font)
        try:
            text_widget.tag_add("italic", "sel.first", "sel.last")
        except tk.TclError:
            messagebox.showwarning("Warning", "No text selected!")

    def set_underline(self):
        text_widget = self.get_current_text_widget()
        underline_font = font.Font(text_widget, text_widget.cget("font"))
        underline_font.config(underline=True)
        text_widget.tag_configure("underline", font=underline_font)
        try:
            text_widget.tag_add("underline", "sel.first", "sel.last")
        except tk.TclError:
            messagebox.showwarning("Warning", "No text selected!")

    def find_text(self):
        text_widget = self.get_current_text_widget()
        search_query = simpledialog.askstring("Find", self.languages[self.current_language]["find"])
        if search_query:
            start = '1.0'
            while True:
                start = text_widget.search(search_query, start, stopindex=tk.END)
                if not start:
                    break
                end = f"{start}+{len(search_query)}c"
                text_widget.tag_add('highlight', start, end)
                start = end
            text_widget.tag_config('highlight', background='yellow')

    def replace_text(self):
        text_widget = self.get_current_text_widget()
        find_query = simpledialog.askstring("Find", self.languages[self.current_language]["find"])
        replace_query = simpledialog.askstring("Replace with", self.languages[self.current_language]["replace"])
        if find_query and replace_query:
            content = text_widget.get("1.0", tk.END).replace(find_query, replace_query)
            text_widget.delete("1.0", tk.END)
            text_widget.insert("1.0", content)


if __name__ == "__main__":
    root = tk.Tk()
    app = SimpleMDIExample(root)
    root.mainloop()

posted @ 2024-11-04 15:43  Elgina  阅读(44)  评论(0)    收藏  举报