python tkinter 如何做一个如下所示的下拉菜单

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python tkinter 如何做一个如下所示的下拉菜单相关的知识,希望对你有一定的参考价值。

Tkinter居然没有这种组件,所以就只能模拟了

#! /usr/bin/python
# -*- coding: utf8 -*-
from Tkinter import *
class Select(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.label = Label(self, text="选择项目")
        self.listBox = Listbox(self, height=1)
        self.button = Button(self, text=\'V\', command=self.triggle)
        self.hideList = True
        for i in xrange(10):
            self.listBox.insert(i, \'Item%d\'%i)
        self.label.grid(row=0, column=0, sticky=N)
        self.listBox.grid(row=0, column=1, sticky=N)
        self.button.grid(row=0, column=2, sticky=N)
        self.grid()
    def triggle(self):
        self.hideList ^= 1
        self.listBox.config(height=[self.listBox.size(), 1][self.hideList])
app = Select()
app.mainloop()

仅供参考。

参考技术A

这个要用ttk库

python37下的示例:

from tkinter import *
import tkinter.ttk #python32以下省略,因为__all__属性已包含ttk,自动导入,python32以下tkinter.ttk改为ttk
tk=Tk()
def re():
    print(c.get())
c = tkinter.ttk.Combobox(tk)
c.grid(row=3,column=1)
c['value'] = ("1","2") #必须str类型或int类型,不支持flont和complex(Python27中是long)类型



具体其他属性参照源码或度娘上搜“tkinter下拉列表”,CSDN里有N个东西

参考技术B

你这不是菜单,你这是下拉列表框,combobox控件。tkinter默认是不带的。

但是TKINTER有一个“隐藏功能”,导入ttk主题库后,你就可以用ComboBox等高级控件了  。

给你个例子,你就知道怎么写了。


#coding:utf-8
import sys
import Tkinter
import Pmw
class Demo:
    def __init__(self, parent):
        parent.configure(background = \'white\')
        self.target = Tkinter.Label(
                parent,
                relief = \'sunken\',
                padx = 20,
                pady = 20,
        )
        self.target.pack(fill = \'x\', padx = 8, pady = 8)
        colours = (\'cornsilk1\', \'snow1\', \'seashell1\', \'antiquewhite1\',
                    \'bisque1\', \'peachpuff1\', \'navajowhite1\', \'lemonchiffon1\',
                    \'ivory1\', \'honeydew1\', \'lavenderblush1\', \'mistyrose1\')
        dropdown = Pmw.ComboBox(
                parent,
                label_text = \'Dropdown ComboBox:\',
                labelpos = \'nw\',
                selectioncommand = self.changeColour,
                scrolledlist_items = colours,
        )
        dropdown.pack(side = \'left\', anchor = \'n\',
                    fill = \'x\', expand = 1, padx = 8, pady = 8)
        first = colours[0]
        dropdown.selectitem(first)
        self.changeColour(first)
    def changeColour(self, colour):
        print \'Colour: \' + colour
        self.target.configure(background = colour)
if __name__ == \'__main__\':
    root = Tkinter.Tk()
    Pmw.initialise(root)
    widget = Demo(root)
    root.mainloop()

Tkinter - python 3 - 循环内循环中的复选框重叠网格

【中文标题】Tkinter - python 3 - 循环内循环中的复选框重叠网格【英文标题】:Tkinter - python 3 - overlapping grid of checkboxes from a loop within a loop 【发布时间】:2021-10-17 03:15:26 【问题描述】:

我这里有这段代码,它运行一个如下所示的窗口:

单击其中一个元素按钮后,我会得到此处显示的同位素结果:

但是,如果我选择另一个按钮,我只会覆盖此处显示的复选框:

我终其一生都无法在显示结果之前找到一种方法来销毁以前的复选框。我尝试了多种方法,我很确定这里SO post 是答案,但我不能100% 确定是否需要将我的结果分成一个范围并相应地附加按钮列表。我正在尝试,但我是前端编程的新手。有谁知道如何让这个东西工作??

代码如下:

import tkinter as tk
from tkinter import ttk
import os
import pandas as pd

__location__ = os.path.realpath(
    os.path.join(os.getcwd(), os.path.dirname(__file__)))


class AppTBL(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent
        self.winfo_toplevel().title("Periodic Table of the Elements")
        self.topLabel = tk.Label(
            self, text="\n\n\n\nClick the element you would like information about.", font=20)
        self.topLabel.grid(row=0, column=0, columnspan=18)
        self.column1 = [
            ('H', 'Hydrogen', '\nAtomic # = 1\nAtomic Weight =1.01\nState = Gas\nCategory = Alkali Metals',),
            ('Li', 'Lithium', '\nAtomic # = 3\nAtomic Weight = 6.94\nState = Solid\nCategory = Alkali Metals'),
            ('Sod', 'Sodium', '\nAtomic # = 11\nAtomic Weight = 22.99\nState = Solid\nCategory = Alkali Metals'),
            ('K', 'Potassium', '\nAtomic # = 19\nAtomic Weight = 39.10\nState = Solid\nCategory = Alkali Metals'),
            ('Rb', 'Rubidium', '\nAtomic # = 37\nAtomic Weight = 85.47\nState = Solid\nCategory = Alkali Metals'),
            ('Cs', 'Cesium', '\nAtomic # = 55\nAtomic Weight = 132.91\nState = Solid\nCategory = Alkali Metals'),
            ('Fr', 'Francium', '\nAtomic # = 87\nAtomic Weight = 223.00\nState = Solid\nCategory = Alkali Metals')]
        r = 1
        c = 0
        for b in self.column1:
            self.elebtn = tk.Button(self,
                                    text=b[0],
                                    width=5,
                                    height=2,
                                    bg="grey",
                                    command=lambda text=b: [self.name(text[1]), self.thebtn(text[1]), self.isotopes(text[0]), self.isodestroy]).grid(row=r, column=c)
            r += 1
            if r > len(self.column1):
                r = 1
                c += 1
        self.infoLine = tk.Label(self, text="", justify='left')
        self.infoLine.grid(row=1, column=3, columnspan=10, rowspan=4)

    def name(self, text):
        self.topLabel.config(text=text)

    def info(self, text):
        self.infoLine.config(text=text)

    def thebtn(self, anything):
        thefile = os.path.join(__location__, 'thefile.txt')
        elementStr = []
        elementStr.append(anything)
        with open(thefile, 'w') as writeit:
            for each in elementStr:
                writeit.write(each)

    def isotopes(self, text):
        isofile = os.path.join(__location__, 'isotope.csv')
        text = text
        df = pd.read_csv(isofile, header=0)
        subset = df[df['element'] == text.upper()]
        subset = subset.astype('isotope': int)
        subindex = subset.index
        numrows = len(subindex)
        r = 1
        c = 2
        r1 = 1
        c1 = 2
        for index, row in subset.iterrows():
            if numrows < 7:
                text = row['isotope']
                isobtn = tk.Checkbutton(self, text=text, width=3,
                                        height=1, fg='brown').grid(row=r, column=c)
                r += 1
                if r > len(self.column1):
                    r = 1
                    c += 1
            elif numrows >= 7:
                text = row['isotope']
                chkbtn = tk.Checkbutton(self, text=text, width=3,
                                        height=1, fg='brown').grid(row=r1, column=c1)
                r1 += 1
                if r1 > len(self.column1):
                    r1 = 1
                    c1 += 1

    def isodestroy(self):
        pass


def endit(gui_sys):
    # self.element_table_callback()
    pass


root = tk.Tk()
root.eval('tk::PlaceWindow . center')
a = AppTBL(root)
a.grid(row=0, column=0, sticky='nsew')
a.bind('<Destroy>', endit)
a.bind('<Button-1>', AppTBL.isodestroy)
a.mainloop()

提前致谢!我已经坚持了两天了,我只是在这里失去理智。

对于 isotopes.csv,如果您复制和粘贴代码,它将不起作用,除非您在同一目录中添加 csv 文件。如果需要,这里有一些示例。您需要在记事本++ 或记事本中将其转换为 csv。如果需要,我也可以在共享驱动器中提供原始文件。

element isotope
H 1
H 2
H 3
H 5
H 6
H 7
HE 10
HE 2
HE 3
HE 4
HE 5
HE 6
HE 7
HE 8
HE 9

答案是:

        for child in self.winfo_children():
        if child.winfo_class() == 'Checkbutton':
            child.destroy()

但这也包括从运行中获取结果,将其附加到数据库中自己的表中。然后在另一个我必须运行两次的函数中再次调用它。在单击按钮之前和之后一次。

【问题讨论】:

【参考方案1】:

如果您想在显示下一个元素的结果之前删除前面的复选框,那么有这样一个选项。 一个小部件有一个方法来获取它的所有孩子的列表,widget.winfo_children()。 您可以为复选框创建容器,例如框架。如有必要,删除框架中的所有元素。

要查看其工作原理,您可以执行以下操作:

def __init__


def __init__(self, parent, *args, **kwargs):
    ...
    # self.infoLine = tk.Label(self, text="", justify='left')
    # self.infoLine.grid(row=1, column=3, columnspan=10, rowspan=4)
    self.frame = tk.Frame(self)
    self.frame.grid(row=1, column=3, columnspan=10, rowspan=4)

def isotopes


def isotopes(self, text):
    # destroy previous checkboxes
    for child in self.frame.winfo_children():
        child.destroy()
    ...
    for index, row in subset.iterrows():
        ...
            isobtn = tk.Checkbutton(self.frame, ...
        ...
            chkbtn = tk.Checkbutton(self.frame, ...

您可能需要重新设计界面以使框架适合窗口。

【讨论】:

目前不起作用,但我将尝试创建另一个框架,它可能适合并在框架中包含一个框架。 这似乎根本不起作用。我可以看到列表,上面有一个框架,但它仍然在下面显示以前的网格。但是,我确实删除了 self.infoline 部分的想法,因为它根本不再被使用,所以我希望我越来越近了。 无论我做什么,新框架都不会使用与原始框架相同的网格布局。如果有帮助,我可以上传主程序的代码,因为它连接到 sqlite db 以获取所有元素。但是,如果您复制并粘贴它,它将不会在您的编辑器中运行。 对我来说正确答案是:对于 self.winfo_children() 中的孩子:if child.winfo_class() == 'Checkbutton': child.destroy() 如果除了要删除的复选框之外没有其他复选框,则可以将窗口中的所有复选框都删除。

以上是关于python tkinter 如何做一个如下所示的下拉菜单的主要内容,如果未能解决你的问题,请参考以下文章

tkinter基础-标签按钮

你如何在 Tkinter 中制作下拉菜单?

如何在 tkinter ~ python 中放置在网格中的两个小部件之间添加空间?

如何使用python中的turtle画一个苹果?

如何安装mysql-python

如何在 iOS 中实现如下图所示的搜索功能?