Py学习  »  Bryan Oakley  »  全部回复
回复总数  12
3 年前
回复了 Bryan Oakley 创建的主题 » Python tkinter使用队列从另一个线程更新Treeview项

你似乎已经把基本知识都记下来了。只需将项目添加到队列中,即可解包并插入到树中。

例如,可以在队列中添加字典:

def work():
  time.sleep(3)
  message = {
      "id": "File1",
      "values": ('tst1', 'tst2')
  }
  tk_thread.send_message_to_ui(message)

在事件处理程序中,可以从消息中提取数据并将其插入到树中:

def process_message_queue(self, event):
    while self.message_queue.empty() is False:
        message = self.message_queue.get(block=False)
        self.tv_files.insert(message['id'], "end", values=message['values'])

如果你想变得更有趣,你可以传递函数名、args和kwargs,这样你的线程就可以在GUI中做任何事情:

发送消息:

def work():
    time.sleep(3)
    message = {
        "attr": "tv_files",
        "method": "insert",
        "args": ("File1", "end"),
        "kwargs": {
            "values": ['tst1', 'tst2']
        },
    }
    tk_thread.send_message_to_ui(message)

处理消息:

def process_message_queue(self, event):
    while self.message_queue.empty() is False:
        message = self.message_queue.get(block=False)
        attr = getattr(self, message['attr'])
        method = getattr(attr, message['method'])
        method(*message['args'], **message['kwargs'])

问题在于这一行:

self._commonVar = Tkinter.StringVar("")

第一个位置参数 StringVar 必须是一个小部件,但是 "" 是字符串而不是小部件。

如果试图显式地将初始值设置为空字符串,请将空字符串指定给 value 论点:

self._commonVar = Tkinter.StringVar(value="")
3 年前
回复了 Bryan Oakley 创建的主题 » Python Tkinter框架销毁以显示新数据

我知道我需要以某种方式破坏帧来重新加载数据。

首先,改变规则 __init__ 只显示起始页。此外,还可以创建字典,将页面名称映射到页面类。

class App(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.pages = {
            "homepage": homepage,
            "page2": page2,
            "page3": page3,
        }

        self.container = tk.Frame(self)
        self.container.pack(side="top", fill="both", expand="true")

        self.switch_frame("homepage")

接下来,修改 switch_frame 销毁 self.container 然后创建请求页面的新实例:

    def switch_frame(self, page_name):
        children = self.container.winfo_children()
        for child in children:
            child.destroy()

        frame_class = self.pages[page_name]
        frame = frame_class(self.container, controller=self)
        frame.pack(fill="both", expand=True)
3 年前
回复了 Bryan Oakley 创建的主题 » Python tkinter:使用列表的地址按钮

聪明的做法是用字典替换单个变量:

btn_sell = {
    "A": Button(...),
    "B": Button(...),
    "C": Button(...),
}
btn_buy = {
    "A": Button(...),
    "B": Button(...),
    "C": Button(...),
}

然后在按钮上循环就变得很简单了:

for label in ("A", "B", "C"):
    btn_sell[label].configure(state="normal")
    btn_buy[label].configure(state="normal")
3 年前
回复了 Bryan Oakley 创建的主题 » python tkinter可以用一条线连接两个帧吗

画布不提供连接对象的方法,但您可以通过简单地在两个对象之间绘制线来模拟它。如果矩形已填充,则可以从一个矩形的中心点到另一个矩形的中心点绘制一条线。然后可以按堆叠顺序降低线条,这样矩形后面的线条部分就不会显示出来。

如果你给这条线一个可以计算的标记,每当其中一个矩形移动时,你也可以重新计算连接它们的线的坐标。

import tkinter as tk
import random

def connect(a,b):
    # compupte the tag, then delete any existing lines
    # between these two objects
    tag = f"connector_{a}_{b}"
    canvas.delete(tag)

    ax0, ay0, ax1, ay1 = canvas.coords(a)
    bx0, by0, bx1, by1 = canvas.coords(b)

    x0 = (ax0 + ax1) / 2
    y0 = (ay0 + ay1) / 2

    x1 = (bx0 + bx1) / 2
    y1 = (by0 + by1) / 2

    # create the line, then lower it below all other
    # objects
    line_id = canvas.create_line(x0, y0, x1, y1, fill="blue", width=4, tags=(tag,))
    canvas.tag_lower(line_id)

def move_rectangles():
    canvas.move(f1, random.randint(-50, 50), 0)
    canvas.move(f2, 0, random.randint(-50, 50))
    connect(f1, f2)

root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=500, background="white")
button = tk.Button(root, text="Move rectangles", command=move_rectangles)

button.pack(side="top")
canvas.pack(side="top", fill="both", expand=True)

f1 = canvas.create_rectangle(50,50, 150, 250, outline="red", fill="white", width=4)
f2 = canvas.create_rectangle(250,100, 350, 350, outline="green", fill="white", width=4)

connect(f1, f2)


root.mainloop()

screenshot

6 年前
回复了 Bryan Oakley 创建的主题 » 通过python文件向Robot框架发送命令行参数

你在评论中写道:

我的目标是从命令行传递凭据。

机器人可以使用 --variable (和 -v )命令行选项。使用此选项将覆盖robot文件中定义的任何导入变量。

例如,可以在测试本身内部设置凭据的默认值:

*** Variables ***
${USER}         test@test.com
${PASSWORD}     test@123
${ENVIRONMENT}  QA1

*** Test cases ***
Example
    log to console  \n*****
    log to console  username: ${USER}
    log to console  password: ${PASSWORD}
    log to console  environment: ${ENVIRONMENT}

可以使用命令行修改这些值 -五 --变量 :

$ robot -v USER:bob -v PASSWORD:bob@123  -v ENVIRONMENT:QA2 ...

如果需要在python函数中访问这些变量而不传入它们,可以使用内置关键字 get_variable_value 要获取值:

from robot.libraries.BuiltIn import BuiltIn
...
user = BuiltIn().get_variable_value('${USER}')

这是因为列表包含对对象的引用。您的列表不包含 [[1 2 3] [1 2 3]] 它是 [<reference to b> <reference to b>] .

当您更改对象时(通过在 b ),您正在更改对象本身,而不是包含该对象的列表。

为了得到你想要的效果,你的清单 a 必须包含 而不是提及 . 若要复制列表,可以使用范围 [:] . 例如:

>>> a=[]
>>> b=[1]
>>> a.append(b[:])
>>> a.append(b[:])
>>> a[0].append(2)
>>> a[1].append(3)
>>> print a
[[1, 2], [1, 3]]

您并不是为每个iframe创建一个单独的字典,您只是不断地修改同一个字典,并不断地在列表中添加对该字典的其他引用。

记住,当你做 content.append(info) ,不是复制数据,只是将引用附加到数据。

您需要为每个iframe创建一个新字典。

for iframe in soup.find_all('iframe'):
   info = {}
    ...

更好的是,你不需要先创建一个空字典。一次全部创建:

for iframe in soup.find_all('iframe'):
    info = {
        "src":    iframe.get('src'),
        "height": iframe.get('height'),
        "width":  iframe.get('width'),
    }
    content.append(info)

有其他方法可以实现这一点,例如遍历属性列表,或者使用列表或字典理解,但是很难提高上述代码的清晰度。

6 年前
回复了 Bryan Oakley 创建的主题 » 销毁标签的python tkinter

问题在于这三行代码:

self.text1 = Label(self, text=count)
self.text1.destroy()
self.text1 = Label(self,text=count)

您正在创建标签, 立刻摧毁它 ,然后重新创建。所以,在这段代码的末尾有一个标签。

下次调用代码时,您已经有了一个标签。然后创建另一个标签(所以,两个),然后立即销毁它(所以,一个),然后立即创建另一个(所以,两个)。

下次调用代码时,您已经有了两个标签。然后创建另一个标签(三个),然后立即销毁它(二个),然后立即创建另一个标签(三个)

…等等。

解决方案是删除这三行代码,创建 self.text1 里面 __init__window ,然后每次调用函数时只更改标签上的文本。

6 年前
回复了 Bryan Oakley 创建的主题 » 用更新的项绑定python tkinter列表框

在列表框中添加或删除数据时不存在内置事件。但是,由于添加和删除数据的是您的代码,因此您可以使用 event_generate 每当更新列表框时。

14 年前
回复了 Bryan Oakley 创建的主题 » 今天(2010年9月)python gui的开发如何?

python 2.7和3.0附带了主题tk(“ttk”)小部件,它们看起来比以前的tk版本要好得多(不过,老实说,任何有能力的GUI开发人员都可以使更老的tk看起来更好)。不要让那些对tk不太了解的人影响你使用它,它仍然是一个非常可行的工具箱,可以完成许多任务。你不会用它来创建一个photoshop克隆,但到底有多少人会编写这种应用程序?

在过去的一年里,我一直在使用wxpython,对于大多数任务,我仍然会选择tkinter而不是tkinter。tkinter更简单,在许多方面更强大。wxwidgets的唯一优点是它有更多的内置的widgets,但是我发现它们中的许多有点麻烦,而且很难使用。对于大多数人会写的应用程序来说,tkinter仍然是一个很好的选择。

这里提供了一些主题小工具的屏幕截图:

http://code.google.com/p/python-ttk/wiki/Screenshots

下面是一个使用Mac上主题小工具的tkinter应用程序的屏幕截图:

http://www.codebykevin.com/phynchronicity-running.png

15 年前
回复了 Bryan Oakley 创建的主题 » 你知道其他有交互模式的编程语言吗,比如python?[关闭]

tcl/tk有一个。从第一天起就一直在那里。这不是Python独有的功能。