#python #user-interface #wxpython
#python #пользовательский интерфейс #wxpython
Вопрос:
Я пытаюсь написать простое приложение, которое позволит перемещать кнопки, я использовал пример, который я нашел здесь, в Stack overflow — извините, я не могу найти исходную ссылку: (
Кнопки перемещаются, как и ожидалось, но как только изменяется размер рамки, позиции кнопок возвращаются в исходное положение, и я не понимаю, поскольку я устанавливаю положение и не уверен, что их сбрасывает и почему.
Код:
import wx
app = wx.App(False)
d = {}
def MouseDown(e):
print('mouse down')
o = e.GetEventObject()
sx,sy = panel.ScreenToClient(o.GetPositionTuple())
dx,dy = panel.ScreenToClient(wx.GetMousePosition())
o._x,o._y = (sx-dx, sy-dy)
d['d'] = o
print(o)
def MouseMove(e):
try:
if 'd' in d:
print("mouse move has been triggered")
o = d['d']
x, y = wx.GetMousePosition()
o.SetPosition(wx.Point(x o._x,y o._y))
except:
print('fail')
pass
def MouseUp(e):
try:
if 'd' in d: del d['d']
except: pass
frame = wx.Frame(None, -1, 'simple.py')
panel = wx.Panel(frame)
box = wx.BoxSizer(wx.VERTICAL)
button1 = wx.Button(panel, -1, "foo")
box.Add(button1, 0, wx.ALL, 10)
button2 = wx.Button(panel, -1, "bar")
box.Add(button2, 0, wx.ALL, 10)
button1.Bind(wx.EVT_LEFT_DOWN, MouseDown)
button2.Bind(wx.EVT_LEFT_DOWN, MouseDown)
button1.Bind(wx.EVT_MOTION, MouseMove)
button2.Bind(wx.EVT_MOTION, MouseMove)
button1.Bind(wx.EVT_LEFT_UP, MouseUp)
button2.Bind(wx.EVT_LEFT_UP, MouseUp)
panel.Bind(wx.EVT_MOTION, MouseMove)
panel.Bind(wx.EVT_LEFT_UP, MouseUp)
panel.SetSizer(box)
panel.Layout()
frame.Show()
app.MainLoop()
Ответ №1:
Это Sizer
перемещение кнопок при изменении размера фрейма.
т. Е. Выполнение своей работы
Разработчик отвечает за размещение его содержимого.
Вы перемещаете элементы вручную, но как только размер рамки изменяется, активируются sizer / s и возвращают работоспособность в макет. Непреднамеренно для вас, отменяя то, что вы хотели, чтобы произошло.
Если вам нужна эта функциональность, которая в реальном приложении привела бы к хаосу (без каламбура), используйте ручное позиционирование и избегайте размеров.
Комментарии:
1. Спасибо за объяснение. Может ли у вас быть ручное позиционирование внутри элемента sizer?
2. @LittleMissChaos Короче говоря, нет. Не так, как вы предлагаете выше в своем коде. С помощью некоторого сложного кодирования вы можете изменить относительные позиции, особенно с помощью a
GridBagSizer
, но, по сути, позиция будет определяться sizer, в зависимости от того, как вы заполнили sizer. Если вы думаете об этом как о команде с определенными позициями игроков, они не могут бесконечно меняться местами во время игры. По сути, разработчик является арбитром, устанавливающим правила. Вы, конечно, можете выбрать бесплатную игру без рефери (sizer
).