Tkinter实现选中两个Checkbutton绘制连线及颜色切换方案咨询
Got it, let's fix this up for you. I've modified your original code to add the line-drawing feature, along with the ability to toggle line color by clicking the first selected checkbox. Here's the complete working code:
from tkinter import * root = Tk() root.title("Checkbutton Connector") # Store checkbutton data: [IntVar, position, widget, x, y] buttons = [] # Store line data: [button1, button2, line_id] lines = [] # Track selected buttons for drawing lines selected_buttons = [] class CMD: """Auxiliary class for callback functions with parameters""" def __init__(self, func, *args): self.func = func self.args = args def __call__(self, *args): combined_args = self.args + args self.func(*combined_args) def toggle_checkbutton_color(pos=0): """Toggle checkbutton background color based on its state""" if buttons[pos][0].get() == 1: buttons[pos][2].configure(bg='red') else: buttons[pos][2].configure(bg='green') def handle_checkbutton_click(pos=0): """Handle checkbutton click: toggle color + manage line selection/drawing""" toggle_checkbutton_color(pos) # Only proceed if line-drawing mode is active if line.get() != 1: return clicked_btn = buttons[pos] # Check if this is the first selected button if not selected_buttons: selected_buttons.append(clicked_btn) # Highlight the selected button temporarily clicked_btn[2].configure(bg='orange') else: # Check if we're clicking the first selected button (to toggle line color) if clicked_btn == selected_buttons[0]: # Find the line connected to this button for line_data in lines: if line_data[0] == clicked_btn: current_color = canvas.itemcget(line_data[2], 'fill') new_color = 'blue' if current_color == 'black' else 'black' canvas.itemconfig(line_data[2], fill=new_color) # Reset selection and revert highlight selected_buttons[0][2].configure(bg='red' if selected_buttons[0][0].get() ==1 else 'green') selected_buttons.clear() else: # Second button selected: draw line between them btn1 = selected_buttons[0] btn2 = clicked_btn # Calculate center coordinates of both buttons btn1_center_x = btn1[3] + btn1[2].winfo_width()//2 btn1_center_y = btn1[4] + btn1[2].winfo_height()//2 btn2_center_x = btn2[3] + btn2[2].winfo_width()//2 btn2_center_y = btn2[4] + btn2[2].winfo_height()//2 # Draw the line on canvas line_id = canvas.create_line(btn1_center_x, btn1_center_y, btn2_center_x, btn2_center_y, fill='black', width=2) lines.append([btn1, btn2, line_id]) # Reset selection and revert highlight selected_buttons[0][2].configure(bg='red' if btn1[0].get() ==1 else 'green') selected_buttons.clear() def place_checkbutton_in_canvas(e): """Place a new checkbutton on canvas when clicking empty area""" # Only place if we're not clicking an existing checkbutton if str(e.widget) == str(canvas): b = IntVar() pos = len(buttons) x = e.x y = e.y # Create checkbutton on canvas btn = Checkbutton(canvas, variable=b, command=CMD(handle_checkbutton_click, pos)) btn.place(x=x, y=y) # Store button data including position buttons.append([b, pos, btn, x, y]) toggle_checkbutton_color(pos) # Create canvas to hold checkbuttons and lines canvas = Canvas(root, width=800, height=600, bg='white') canvas.pack(fill=BOTH, expand=True) # Line-drawing mode toggle line = IntVar() draw_line_check = Checkbutton(root, text="Enable Line Drawing", variable=line) draw_line_check.pack(side=TOP, anchor=W, padx=5, pady=5) # Bind canvas click to add checkbuttons canvas.bind('<Button-1>', place_checkbutton_in_canvas) root.mainloop()
Key Changes & Explanations:
- Switched to Canvas Container: I replaced direct placement on
rootwith aCanvaswidget. This lets us draw lines directly on the same surface as the checkbuttons, which is far more manageable for interactive drawing. - Enhanced Button Tracking: Each checkbutton now stores its x/y position along with its widget and state variable, so we can calculate center points for drawing lines.
- Combined Click Handler: The
handle_checkbutton_clickfunction now does two things: toggles the button's color and manages the line-selection workflow when line-drawing mode is active. - Line Drawing Logic:
- When line mode is on, clicking the first checkbutton highlights it temporarily (orange)
- Clicking a second checkbutton draws a black line between their centers
- Clicking the first selected button again toggles the line's color between black and blue
- Line State Storage: The
lineslist keeps track of all drawn lines and their associated buttons, so we can find and modify lines later when toggling colors.
内容的提问来源于stack exchange,提问作者fernando
相关产品推荐
相关产品推荐

