Если кому-то это все еще нужно - вот простой код для создания виджета Calendar и DateEntry с использованием пакета tkcalendar.
pip install tkcalendar [для установки пакета]
try:
import tkinter as tk
from tkinter import ttk
except ImportError:
import Tkinter as tk
import ttk
from tkcalendar import Calendar, DateEntry
def example1():
def print_sel():
print(cal.selection_get())
top = tk.Toplevel(root)
cal = Calendar(top,
font="Arial 14", selectmode='day',
cursor="hand1", year=2018, month=2, day=5)
cal.pack(fill="both", expand=True)
ttk.Button(top, text="ok", command=print_sel).pack()
def example2():
top = tk.Toplevel(root)
ttk.Label(top, text='Choose date').pack(padx=10, pady=10)
cal = DateEntry(top, width=12, background='darkblue',
foreground='white', borderwidth=2)
cal.pack(padx=10, pady=10)
root = tk.Tk()
s = ttk.Style(root)
s.theme_use('clam')
ttk.Button(root, text='Calendar', command=example1).pack(padx=10, pady=10)
ttk.Button(root, text='DateEntry', command=example2).pack(padx=10, pady=10)
root.mainloop()
Эту проблему можно решить, используя кортежи boost . Это приведет к дизайну, который отличается от того, о котором вы думаете сейчас, но он должен позволить вам решить проблему общим способом.
В следующем примере определяется запись формы "std :: string, bool "а затем считывает эти данные из потока.
#include "boost/tuple/tuple.hpp"
#include <iostream>
#include <sstream>
using namespace ::boost::tuples;
Функции используются для чтения данных из потока. Первая перегрузка останавливает итерацию по кортежу после того, как мы достигаем последнего типа записи:
//
// This is needed to stop when we have no more fields
void read_tuple (std::istream & is, boost::tuples::null_type )
{
}
template <typename TupleType>
void read_tuple (std::istream & is, TupleType & tuple)
{
is >> tuple.template get_head ();
read_tuple (is, tuple.template get_tail ());
}
Следующий класс реализует член-получатель для нашей записи. Используя RecordKind в качестве ключа, мы получаем конкретный элемент, который нас интересует.
template <typename TupleType>
class Record
{
private:
TupleType m_tuple;
public:
//
// For a given member - get the value
template <unsigned int MBR>
typename element <MBR, TupleType>::type & getMember ()
{
return m_tuple.template get<MBR> ();
}
friend std::istream & operator>> (std::istream & is
, Record<TupleType> & record)
{
read_tuple (is, record.m_tuple);
}
};
Следующий тип - это метаописание для нашей записи. Перечисление дает нам символическое имя, которое мы можем использовать для доступа к членам, т.е. имена полей.
Я мог бы поиграть с миксином записи, чтобы сделать что-то подобное - добавить функциональность в класс автоматически во время компиляции
template<class Base, class XyzRecType>
class CRecord : public Base
{
protected:
RecType xyz;
public:
CRecord() : Base() {}
RecType Get() {return xyz;}
void Set(const RecType& anXyz) {xyz = anXyz;}
void ReadFromStream( std::istream& input)
{
...
}
};
class CMyClass
{
};
int main()
{
// now thanks to the magic of inheritance, my class has added methods!
CRecord<CMyClass, std::string> myClassWithAStringRecord;
myClassWithAStringRecord.Set("Hello");
}
Я не совсем уверен, что вы ищете в некоторых случаях.
Похоже, вы пытаетесь создать механизм для загрузки и доступа к дисковым структурам произвольной структуры. Это точно? (Правка: только что заметил функцию-член "set" ... так что я думаю, вы ищете полную сериализацию)
Если вы используете систему * nix, укажите свой собственный компилятор для компиляции в .o (вероятно, perl / python / what-have-you, который завершается вызовом gcc) в Makefile - тривиальное решение. Другие могут знать, как это сделать в Windows.
Если вы ищете способ сериализации / десериализации данных с помощью генерации кода C ++, я бы посмотрел на Google protobufs ( http://code.google.com/p/protobuf / ) или Facebook Thrift ( http://incubator.apache.org/thrift/ ).
Для protobufs вы пишете определение данных следующим образом:
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
Класс человека C ++ затем создается, что позволяет загружать, сохранять и получать доступ к этим данным. Вы также можете сгенерировать python, java и т. Д.
Это метод, который я часто использую в C и C ++, он называется "макрос списка". Предположим, у вас есть список таких вещей, как переменные, сообщения об ошибках, коды операций интерпретатора или что-то еще, о том, какой повторяющийся код необходимо написать. В вашем случае это переменные-члены класса.
Предположим, это переменные. Поместите их в макрос списка следующим образом:
#define MYVARS \
DEFVAR(int, a, 6) \
DEFVAR(double, b, 37.3) \
DEFARR(char, cc, 512) \
Чтобы объявить переменные, сделайте следующее:
#define DEFVAR(typ,nam,inival) typ nam = inival;
#define DEFARR(typ,nam,len) typ nam[len];
MYVARS
#undef DEFVAR
#undef DEFARR
Теперь вы можете сгенерировать любой тип повторяющегося кода, просто переопределив DEFVAR и DEFARR и создав экземпляр MYVARS.
Некоторые люди находят это довольно неприятно, но я думаю, что это отличный способ использовать препроцессор в качестве генератора кода и выполнить СУХОЙ. И,