Найти - Пользователи
Полная версия: Определение выбранного пункта меню (Tkinter)
Начало » GUI » Определение выбранного пункта меню (Tkinter)
1 2
SirJorah
Уважаемые коллеги! Есть такой нехитрый код:
    def createMenu(self, master = None):
        self.mb = Menubutton(master, indicatoron = 1)
        self.mb.pack(padx = 2, pady = 1)
        self.menu = Menu(self.mb, tearoff = 0, bg = 'white')
        self.mb.configure(menu = self.menu)
        return self.mb
    def ConnectACAD(self):
        self.acad = GetActiveObject("AutoCAD.Application")
        self.dwg = self.acad.ActiveDocument
        self.mspace = self.dwg.ModelSpace
        self.master.title(self.title+' - '+self.dwg.Name.encode('utf-8'))
        for layer in self.dwg.Layers:
            self.menu.add_command(label = layer.Name, command = self.SetActiveLayer)
        self.mb.configure(text = self.menu.entrycget(0, 'label'))
        
    def SetActiveLayer(self):
        self.RefreshDisplay(self.menu.entrycget(ACTIVE, 'label'))
        
    def RefreshDisplay(self, layerString):
        self.mb.configure(text = layerString)
В данном случае меню в связке с Menubutton эмулирует отсутствующий в Tkinter ComboBox. Пункты меню именуются соответственно наименованиям слоев активного чертежа в AutoCAD. По освященной веками традиции ComboBox выбор пункта меню должен приводить к отображению наименования выбранного пункта на кнопке Menubutton (именно это пытается сделать процедура RefreshDisplay). Однако выбор любого пункта меню приводит к исчезновению надписи с Menubutton, т.е. entrycget возвращает пустую строку. Код обработчиков заимствован с данного весьма толкового ресурса: http://www.russianlutheran.org/python/nardo/nardo.html Вопрос: как правильно идентифицировать выбранный пункт меню? Заранее признателен за рекомендации.
4kpt_III
Очень просто. Использовать анонимную функцию lambda. Только не забудьте, что в цикле нужно объект слоя передавать явно.
SirJorah
Уважаемый друг! Огромное спасибо! Благодаря Вам изучил применение lambda в Tkinter. Вот так все работает:
    def ConnectACAD(self):
        self.acad = GetActiveObject("AutoCAD.Application")
        self.dwg = self.acad.ActiveDocument
        self.mspace = self.dwg.ModelSpace
        self.master.title(self.title+' - '+self.dwg.Name.encode('utf-8'))
        for x in xrange(0,self.dwg.Layers.Count) :
            self.menu.add_command(label = self.dwg.Layers[x].Name, command = lambda z = x: self.SetActiveLayer(z))
        self.MenuVar.set(self.menu.entrycget(0, 'label'))
        
    def SetActiveLayer(self, idx):
        self.MenuVar.set(self.menu.entrycget(idx, 'label'))
4kpt_III
Да пожалуйста.
Теперь минусы кода:
1. Не надо делать from tkinter import *
2. В свободное время почитайте про PEP8.
3. Почему:

command = lambda z = x: self.SetActiveLayer(z)

Так же логичнее

command=lambda x=x: self.SetActiveLayer(x)

P.S. Удачи в разработке. Сам долгое время проработал с Autocad…
SirJorah
Согласен. x=x тоже работает. И что не следует делать from tkinter import * - тоже поддерживаю. В действующем проекте (http://sourceforge.net/projects/xml2mif/) у меня так и написано:
from Tkinter import Tk, Button, Frame, Label, LabelFrame, Radiobutton, Entry, Text, Scrollbar, IntVar
from Tkinter import DISABLED, NORMAL, END
from tkFileDialog import Open, Directory
И про PEP8 почитаю. По Вашему совету - точно найду время. Еще раз благодарю.
4kpt_III
Да. Так действительно лучше, но…

from Tkinter import DISABLED, NORMAL, END

Гляньте, что там внутри
SirJorah
Хо-хо, глянуть еще не успел, но подозреваю, что как и в случае с упомянутой уважаемым Микки Нардо переменной (или скорее предполагается что константой) ACTIVE:
DISABLED = ‘disabled’
NORMAL = ‘normal’
END = ‘end’
))))
Кстати, если Вы долго работали с автокадом, может подкинете идейку, как обратиться к внутренней базе данных чертежа? db = dwg.Database срабатывает, а вот дальше - никакие StartTransaction не прокатывают. А лопатить чертеж с over 56K графических объектов, чтобы выбрать например все полилинии, принадлежащие определенному слою, по времени долго, тем более что ясно - можно быстрее, ведь команда QuickSelect конечно тоже немного думает, но в сравнении с полным перебором отвечает практически мгновенно.
4kpt_III
Работал как пользователь. Не в разрезе программирования
SirJorah
Ясно. Как пользователь я уж тоже давно тружусь. Программировать было пытался на Delphi, но из-за недостатка внятной документации бросил. Перешел на ГИС ObjectLand - там объектная модель в хелпе детально описана, поэтому не составляет труда внедрить окно карты в свою форму и тащить оттуда координаты полигонов (земельных участков), чтобы потом сформировать межевой план. Но сейчас работаю в конторе, где используют только автокад, поскольку съемку первоначально формируют топографы, потом с ней работают геологи, геофизики, гидрологи - и только в самом конце все это поступает в наш отдел, где мы должны разработать проект межевания земельных участков. Объекты тянутся на сотни километров, участков получаются тоже сотни, если не тысячи - и для каждого надо сформировать ведомость координат. Так что даже полным перебором объектов лучше, чем вручную. Выкину перебор объектов чертежа в отдельный поток, чтобы форма не “замерзала”, а тем временем продолжу искать подступы к database. Вот так как-то )))
Andrey Skobeldin
ИМХО, в Акаде, для выбора геометрических примитивов из какого либо пространства по определенным критериям лучше сформировать SelectionSet, а потом уже его проитерировать чтоли.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB