При определении переменной внутри функции, если вы не используете global
, тогда функция будет предполагать, что вы хотите назначить эту переменную только локально. В основном это будет означать, что ничто другое в вашем коде не может получить доступ к этой переменной, если вы не пометите ее как global
или не передадите ее непосредственно другой функции.
Итак, добавьте это:
global trennzeichenentry
В функции menubaroptions
, например, так:
def menubaroptions(root):
global trennzeichenentry
Вам также нужно будет определить глобальное в другом методе. Все это говорит о том, что вы действительно не хотите использовать global в классе, и ваш класс должен быть переработан, чтобы компенсировать это должным образом.
Вот упрощенная версия вашего кода, которая показывает, как настроить поля ввода в качестве атрибута класса, чтобы вы могли избежать глобальных переменных.
import tkinter as tk
class GraphicalUserInterface(tk.Tk):
def __init__(self):
super().__init__()
self.minsize(560, 105)
self.entry_string = tk.IntVar()
self.taktzykluszeit = tk.DoubleVar()
self.menubar_options()
tk.Button(self, text='print entries', command=self.method_i_want_to_call_the_variable_in).grid()
def menubar_options(self):
optionswindow = tk.Toplevel(self)
optionswindow.minsize(300, 150)
tk.Label(optionswindow, text="Length of Separator in Byte:").pack()
self.trennzeichenentry = tk.Entry(optionswindow, textvariable=self.entry_string, width=30, justify="center")
self.trennzeichenentry.pack()
tk.Label(optionswindow, text="Measurementtime for all \n Temperature-Sensors in sec").pack()
self.taktzykluszeitentry = tk.Entry(optionswindow, textvariable=self.taktzykluszeit, width=30, justify="center")
self.taktzykluszeitentry.pack()
def method_i_want_to_call_the_variable_in(self):
print(self.trennzeichenentry.get())
print(self.taktzykluszeitentry.get())
if __name__ == '__main__':
GraphicalUserInterface().mainloop()
Вы могли создать неявную перегрузку оператора. Затем можно создать Стрингфилд из строк как это:
StringField field = "value of new object";
string value=(string)field;
Знайте, что это создает новый объект StringField. Я не был бы neccesarily совет Вы, чтобы сделать это.
[System.Diagnostics.DebuggerDisplay("{Value}")]
public class StringField
{
public string Value { get; set; }
public static implicit operator StringField(string s)
{
return new StringField { Value = s };
}
public static explicit operator string(StringField f)
{
return f.Value;
}
public override string ToString()
{
return Value;
}
}
Вы можете, имел StringField путем отображения свойства Name на Имя. Поле значения внутренне в Вашем классе.
таким образом, можно определить свойство Name как это:
string Name
{
get { return _name.Value; }
set { _name.Value = value; }
}
Здесь _name является Вашей переменной StringField.
Можно реализовать присвоение путем обеспечения оператора преобразования. Учитывая природу Вашего класса, необходимо также переопределить Методы объекта:
public class StringField {
public string Value { get; set; }
public static implicit operator StringField(string value) {
StringField sf = new StringField();
sf.Value = value;
return sf;
}
public override string ToString() {
return Value;
}
public override bool Equals(object obj) {
if (obj == null || !(obj is StringField)) return false;
return 0 == string.Compare(Value, (obj as StringField).Value);
}
public override int GetHashCode() {
return Value.GetHashCode();
}
}
Привязка данных ре, для некоторых обязательных целей (PropertyGrid
, DataGridView
, и т.д.), можно сделать это с a TypeConverter
(см. ниже). К сожалению, это, кажется, не работает с TextBox
, таким образом, я думаю, что Ваш наилучший вариант состоит в том, чтобы просто добавить свойство контейнера (как уже предложено):
string NameString
{
get { return Name.Value; }
set { Name.Value = value; } // or new blah...
}
(и свяжите с NameString
)
В прошлом я использовал пользовательский PropertyDescriptor
реализации для обхождения этого но это не стоит того только для этого.
Так или иначе, a TypeConverter
пример (работает с PropertyGrid
и DataGridView
):
[TypeConverter(typeof(StringFieldConverter))]
public class StringField
{
public StringField() : this("") { }
public StringField(string value) { Value = value; }
public string Value { get; private set; }
}
class StringFieldConverter : TypeConverter
{
public override bool CanConvertFrom(
ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string)
|| base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(
ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value)
{
string s = value as string;
if (s != null) return new StringField(s);
return base.ConvertFrom(context, culture, value);
}
public override bool CanConvertTo(
ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(string)
|| base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(
ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value, Type destinationType)
{
if (destinationType == typeof(string) && value != null
&& value is StringField)
{
return ((StringField)value).Value;
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
Оператор присваивания не может быть переопределен в C#. У Вас могло однако быть свойство, чтобы сделать преобразование типов для Вас и выставить то класс