You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter实现选中两个Checkbutton绘制连线及颜色切换方案咨询

Solution for Tkinter Checkbutton Connection & Line Color Toggle

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 root with a Canvas widget. 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_click function 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 lines list keeps track of all drawn lines and their associated buttons, so we can find and modify lines later when toggling colors.

内容的提问来源于stack exchange,提问作者fernando

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 20:37:38