Tkinter entry.get() не обновляет [Gurobi Python]

Для более простой демонстрации моей проблемы я использую очень простую линейную программу. Я хочу установить в правой части одного ограничения определенное значение, которое я ввожу в поле ввода (Tkinter). Когда я нажимаю на кнопку, в метке будут отображаться переменные, не равные нулю.

Проблема: начальное значение поля ввода равно 0. Когда я изменяю его, например, на 100 я все еще получаю те же результаты. Результаты не меняют того, что я ввожу в поле ввода. Когда я жестко запрограммирую правостороннее значение ограничения на любое другое значение, результаты изменятся, но не в том случае, если я изменю его в своем поле ввода.

Похоже, что бы я ни вводил в поле ввода, Python всегда принимает начальное значение, равное 0. Он не обновляется до того, что я набрал.

import Tkinter as tk
from gurobipy import *



WIDTH = 330
HEIGHT = 500

root = tk.Tk()
canvas = tk.Canvas(root, height=HEIGHT, width=WIDTH)
canvas.pack()

conslabel = tk.Label(root, text='Constraint value')
conslabel.place(relx=0.1, rely = 0.02)


var = tk.IntVar()
entry = tk.Entry(root, textvariable=var)
entry.place(relx=0.5, rely=0.02, relwidth=0.3)


button = tk.Button(root, text = "yield result", command = lambda: [setEntryValue(), build_model(entryValue), m.optimize(), results(), m.reset()])
button.place(relx = 0.5, rely = 0.675, anchor = tk.CENTER)

outputLabel = tk.Label(root, bg='white')
outputLabel.place(relx = 0.5, rely = 0.85, anchor = tk.CENTER, relheight = 0.2, relwidth = 0.8)

entryValue = 0

def build_model(entryValue):
    m = Model("lp1")
    m.setParam('OutputFlag', False)

    x1 = m.addVar(name="x1")
    x2 = m.addVar(name="x2")

    m.update()

    m.setObjective(5*x1 + 4*x2, GRB.MAXIMIZE)
    m.addConstr(6*x1 + 4*x2 <= 24, "constr_1")
    m.addConstr(1*x1 + 2*x2 <= 6, "constr_2")
    m.addConstr(-1*x1 + 1*x2 <= 1, "constr_3")
    m.addConstr(x2 <= entryValue, "constr_4")

def setEntryValue():
    global entryValue
    entryValue = var.get()
    return entryValue


def labeltext(): 
    finalvars = ''
    for v in m.getVars():
        if v.x != 0:
            finalvars += ' ' + str(v.varName)
    return finalvars

def results():
    for v in m.getVars():
        print('%s: %f' % (v.varName, v.x))  
    print('Obj: %f' % m.objVal)  
    outputLabel['text'] = labeltext()

root.mainloop()


person floschen    schedule 09.12.2019    source источник
comment
Это ничего не делает: m.optimize и это статично: x2 <= entryValue   -  person stovfl    schedule 09.12.2019
comment
упс, да, я забыл удалить m.optimize, но что означает статическое значение x2 ‹= entryValue? Я знаю статику только с точки зрения функций... спасибо за помощь   -  person floschen    schedule 09.12.2019
comment
что означает, что x2 ‹= entryValue является статическим? : entryValue – это начальное значение, которое никогда не будет привязано к цепочке.   -  person stovfl    schedule 09.12.2019
comment
@BryanOakley покажите определение для addVar: Можем ли мы сделать: .addVar(name="entry") и позже (x2 <= entry.get()   -  person stovfl    schedule 09.12.2019
comment
Хорошо, это становится действительно странным, я написал функцию setEntryValue(), которая представляет собой просто entryValue = int(entry.get()) и функцию build_model(), которая создает модель, и я поместил эти две функции в набор лямбда команда кнопки, поэтому, когда я сначала нажимаю кнопку, для entryValue будет установлено значение entry.get(), а затем создается модель, и она по-прежнему всегда принимает начальный 0 записи... Я собираюсь обновить код   -  person floschen    schedule 09.12.2019
comment
функция setEntryValue(), которая просто entryValue = int(entry.get()): это не будет работать по двум причинам: 1. entryValue является local для def setEntryValue и бесполезно. 2. Согласно update-the-model-after-editing После того как вы вызываете Model.addConstr(), он использует значения entryValue для создания ограничения без какой-либо ссылки на entryValue   -  person stovfl    schedule 09.12.2019
comment
хорошо, я изменил его на global entryValue, чтобы решить первую проблему.. для второй проблемы: когда я сначала нажимаю кнопку, entryValue будет установлен на то, что было введено в соответствии с функцией setEntryValue(), а затем модель строится с помощью функция build_model(entryValue)... она создается после обновления entryValue. Я действительно не понимаю, почему она все еще принимает начальное значение... и большое спасибо за вашу помощь до сих пор   -  person floschen    schedule 09.12.2019
comment
не понимаю, почему он по-прежнему принимает начальное значение: это из-за использования lambda:. Использование lambda примет начальное значение, равное 0, и передаст его build_model(entryValue). Удалите параметр, используйте def build_model()   -  person stovfl    schedule 09.12.2019
comment
Соответствующее Gurobi python изменяет значение определенного значения   -  person stovfl    schedule 09.12.2019


Ответы (2)


Вы получаете значение виджета Entry примерно через миллисекунду после его создания, задолго до того, как пользователь сможет что-либо ввести. entryValue не обновляется, когда пользователь вводит данные.

Вам нужно подождать, чтобы вызвать entry.get(), пока пользователь не сможет ввести данные. Обычно это означает сделать это в обратном вызове, связанном с кнопкой или пунктом меню.

Вы должны создать функцию для кнопки «результат доходности» вместо использования lambda. Затем в этой функции вы можете настроить свои данные и вычислить результат.

Это должно выглядеть примерно так:

def yield_result():

    entryValue = int(entry.get())

    m.setObjective(5*x1 + 4*x2, GRB.MAXIMIZE)
    m.addConstr(6*x1 + 4*x2 <= 24, "constr_1")
    m.addConstr(1*x1 + 2*x2 <= 6, "constr_2")
    m.addConstr(-1*x1 + 1*x2 <= 1, "constr_3")
    m.addConstr(x2 <= entryValue, "constr_4")

    return [m.optimize(), results()]
...    
button = tk.Button(root, text = "yield result", command = yield_result)
person Bryan Oakley    schedule 09.12.2019

Я думаю, проблема в том, что вам нужно присвоить текстовую переменную вашей записи:

entry_var = tk.StringVar()
entry = tk.Entry(root, textvar = entry_var)

когда вы хотите получить текст в поле ввода, вы можете просто использовать string = entry_var.get()

person EvilTaco    schedule 09.12.2019
comment
Я устал от этого с var = tk.IntVar() entry = tk.Entry(root, textvariable=var) и позже entryValue = var.get()before, но это не сработало, соответственно. у меня точно такая же проблема к сожалению - person floschen; 09.12.2019
comment
StringVar редко требуется с виджетом Entry и не решает эту конкретную проблему. - person Bryan Oakley; 09.12.2019