一、简介

       Qt的demo中有CalendarWidget的里,本程序将其国际化,并随时隐藏不必要的设计部件,根据网上的例子增加了一些配置按钮和公历对农历的一些转换,并修复了一些故障。主要目的是掌握其布局的紧凑,并熟悉一些部件的隐藏操作。

二、运行图

(1)程序运行,显示当前的日历,如下图1所示。

ios 日历 Widget开发 widgetsmith设置日历_Layout

三、详解

 

1、时钟按钮

点击第二个按钮为时钟按钮(第一个按钮为回到今天的日期),其显示如下图2所示。

 

ios 日历 Widget开发 widgetsmith设置日历_ios 日历 Widget开发_02

时钟显示的是当前的时间,具体的设计可以参看本分类中的相应的文章。

 

 

 

2、设置按钮

 

 

void Window::ConfigureButtonClicked()
{
    if (m_ConfigureButton->text() == tr("display")) {
        generalOptionsGroupBox->setHidden(false);
        datesGroupBox->setHidden(false);
        textFormatsGroupBox->setHidden(false);
        m_ConfigureButton->setText(tr("hidden"));
        m_ConfigureButton->setToolTip(tr("hide setup"));

        previewGroupBox->setTitle(tr("Preview"));
    }
    else if (m_ConfigureButton->text() == tr("hidden")) {
        generalOptionsGroupBox->setHidden(true);
        datesGroupBox->setHidden(true);
        textFormatsGroupBox->setHidden(true);
        m_ConfigureButton->setText(tr("display"));
        m_ConfigureButton->setToolTip(tr("display setup"));

        previewGroupBox->setTitle(tr("Calendar"));
    }
}

 

点击第三个按钮为显示设置按钮,再次点击将隐藏部分部件,回到图1,点击后其显示如下图3所示。

 

ios 日历 Widget开发 widgetsmith设置日历_ios 日历 Widget开发_03

 

大体的配置跟Qtdemo的例子很相像,增加了设置自己的生日和前往自己的生日按钮,和回到今天。

ios 日历 Widget开发 widgetsmith设置日历_ios 日历 Widget开发_04

ios 日历 Widget开发 widgetsmith设置日历_Layout_05

 

SetBirthday::SetBirthday(QWidget *parent) :
    QDialog(parent)
{
    QLabel* birthdayLabel = new QLabel(tr("birthday:"));

    birthdayDateEdit = new QDateEdit(QDate::currentDate(), this);
    birthdayDateEdit->setDisplayFormat("yyyy-MM-dd");
    QHBoxLayout* editLayout = new QHBoxLayout;
    editLayout->addWidget(birthdayLabel);
    editLayout->addWidget(birthdayDateEdit);

    QPushButton* okBtn = new QPushButton(tr("ok"));
    QPushButton* cancelBtn = new QPushButton(tr("cancle"));
    QHBoxLayout* btnLayout = new QHBoxLayout;
    btnLayout->setSpacing(20);
    btnLayout->addWidget(okBtn);
    btnLayout->addWidget(cancelBtn);

    QVBoxLayout* dlgLayout = new QVBoxLayout;
    dlgLayout->setMargin(10);
    dlgLayout->addLayout(editLayout);
    dlgLayout->addStretch(10);
    dlgLayout->addLayout(btnLayout);
    setLayout(dlgLayout);

    connect(okBtn, SIGNAL(clicked()), this, SLOT(accept()));
    connect(cancelBtn, SIGNAL(clicked()), this, SLOT(reject()));

    setWindowTitle(tr("set_birthday"));
    resize(200, 100);
}

 

 

3、关于按钮

 

 

void Window::AboutButtonClicked()
{
    QMessageBox::about(this, tr("About Calendar"),
         tr("<h1> Calendar 2014</h1>"

         "<p><h4>Release 1.0</h4>"
         "<p>Copyright © 2013-2014 Inc. & isoft "
         "All rights reserved."
         "<p>版权所有 © 2013-2014 Inc. & isoft。 保留所有权利。"
         "<p>警告:本计算机程序受著作权法和国际公约的保护,未经授权擅自复制或传播本程序"
         "的部分或全部,可能受到严厉的民事及刑事制裁,并将在法律许可的范围内受到最大"
         "可能的起诉。"
            ));
}

 

点击第四个按钮为关于产品的按钮,其内容可以自己设定,只需修改QString的内容,其显示如下图4所示。

 

ios 日历 Widget开发 widgetsmith设置日历_ios 日历 Widget开发_06

 

 

4、公历转农历

       公历转农历的程序在本分类的博文中也有详细的介绍,可以参照,但只能计算1921-2021年间的农历,当超出了这个范围就无法显示农历了,网上也有建议使用sqlite读取了一个农历的数据库,但不知道农历数据库怎么创建起来,所以以后再考虑。显示结果如下图5所示。

 

ios 日历 Widget开发 widgetsmith设置日历_Qt_07

 

void Window::selectedDateChanged()
{
    QString outLunarMD = "", outLunarYear = "", outLunarMonth = "", outLunarDay = "";
    currentDateEdit->setDate(calendar->selectedDate());
    m_detail->setText(calendar->selectedDate().toString("yyyy-MM-dd dddd"));
    m_day->setText(calendar->selectedDate().toString("dd"));

    if (((calendar->selectedDate().year() > 1921 )
        || (calendar->selectedDate().year() == 1921 && calendar->selectedDate().month() > 2)
        || (calendar->selectedDate().year() == 1921 && calendar->selectedDate().month() == 2 && calendar->selectedDate().day() >= 8))
        && (calendar->selectedDate().year() < 2021))
    {
        get_chinese_calendar(calendar->selectedDate(), outLunarMD, outLunarYear, outLunarMonth, outLunarDay);
        m_mouthday->setVisible(true);
        m_gregorian->setVisible(true);
        m_mouthday->setText(outLunarMD);
        m_gregorian->setText(outLunarYear + " " + outLunarMonth + " " + outLunarDay);
    }
    else {
        m_mouthday->setVisible(false);
        m_gregorian->setVisible(false);
    }
}

 

 

5、保存配置信息

      因本程序配置信息比较多,采用QSettings m_settings("i-soft.com.cn", "calendar");保存上次配置的信息,下次程序启动时用户不用在重新配置。

 

 

void Window::ReadHistorySettings()
{
    QSettings m_settings("i-soft.com.cn", "calendar");
    localeCombo->setCurrentIndex(m_settings.value("Language").toInt());
    firstDayCombo->setCurrentIndex(m_settings.value("WeekStart").toInt());
    selectionModeCombo->setCurrentIndex(m_settings.value("Selection_Mode").toInt());
    gridCheckBox->setChecked(m_settings.value("Show_Grid").toBool());
    navigationCheckBox->setChecked(m_settings.value("Show_Navigation_Bar").toBool());
    horizontalHeaderCombo->setCurrentIndex(m_settings.value("Horizontal_Header").toInt());
    verticalHeaderCombo->setCurrentIndex(m_settings.value("Vertival_Header").toInt());
    weekdayColorCombo->setCurrentIndex(m_settings.value("WeekdayColor").toInt());
    weekendColorCombo->setCurrentIndex(m_settings.value("WeekendColor").toInt());
    headerTextFormatCombo->setCurrentIndex(m_settings.value("Header_Font").toInt());
    firstFridayCheckBox->setChecked(m_settings.value("First_Friday").toBool());
    mayFirstCheckBox->setChecked(m_settings.value("May_First").toBool());
    m_clock->restoreGeometry(m_settings.value("Clock_Geometry").toByteArray());
    m_Birthday = QDate::fromString(m_settings.value("Birthday_Date").toString(), "yyyy-MM-dd");
    this->restoreGeometry(m_settings.value("Calendar_Geometry").toByteArray());

    if (m_Birthday.isNull())
        goBirthday->setEnabled(false);
}

void Window::WriteCurrentSettings()
{
    QSettings m_settings("i-soft.com.cn", "calendar");
    m_settings.setValue("Language", localeCombo->currentIndex());
    m_settings.setValue("WeekStart", firstDayCombo->currentIndex());
    m_settings.setValue("Selection_Mode", selectionModeCombo->currentIndex());
    m_settings.setValue("Show_Grid", gridCheckBox->isChecked());
    m_settings.setValue("Show_Navigation_Bar", navigationCheckBox->isChecked());
    m_settings.setValue("Horizontal_Header", horizontalHeaderCombo->currentIndex());
    m_settings.setValue("Vertival_Header", verticalHeaderCombo->currentIndex());
    m_settings.setValue("WeekdayColor", weekdayColorCombo->currentIndex());
    m_settings.setValue("WeekendColor", weekendColorCombo->currentIndex());
    m_settings.setValue("Header_Font", headerTextFormatCombo->currentIndex());
    m_settings.setValue("First_Friday", firstFridayCheckBox->isChecked());
    m_settings.setValue("May_First", mayFirstCheckBox->isChecked());
    m_settings.setValue("Clock_Geometry", m_clock->saveGeometry());
    m_settings.setValue("Birthday_Date", m_Birthday.toString ("yyyy-MM-dd"));
    m_settings.setValue("Calendar_Geometry", this->saveGeometry());
}

        配置文件会由系统生成(当然也可以自己定义配置文件settings = QSettings("./config.ini", QSettings.IniFormat)),windows下是在注册表里,linux是在当前用户目录下的.config文件中如/home/aoyang/.config/i-soft.com.cn。打开文件的内容如下图6所示。

 

ios 日历 Widget开发 widgetsmith设置日历_ios 日历 Widget开发_08

 

6、鼠标右键

 

 

{
       // TODO:  Context Menu
        m_ReturnTodayAction = new QAction(tr("Mtoday"), this);
        m_ReturnTodayAction->setIcon(QIcon(":/images/go_back_today.png"));
        m_ReturnTodayAction->setShortcut(tr("F9"));
        m_ShowClockAction = new QAction(tr("Mclock"), this);
        m_ShowClockAction->setIcon(QIcon(":/images/clock.ico"));
        m_ShowClockAction->setShortcut(tr("F10"));
        m_ConfigureButtonAction = new QAction(tr("Msetup"), this);
        m_ConfigureButtonAction->setIcon(QIcon(":/images/configure.png"));
        m_ConfigureButtonAction->setShortcut(tr("Ctrl+G"));
        connect(m_ReturnTodayAction, SIGNAL(triggered()), this, SLOT(ReturnToday()));
        connect(m_ShowClockAction, SIGNAL(triggered()), SLOT(ShowClockButtonClicked()));
        connect(m_ConfigureButtonAction, SIGNAL(triggered()), this, SLOT(ConfigureButtonClicked()));
}
void Window::CreateContextMenu()
{
    previewGroupBox->addAction(m_ReturnTodayAction);
    previewGroupBox->addAction(m_ShowClockAction);
    previewGroupBox->addAction(m_ConfigureButtonAction);
    previewGroupBox->setContextMenuPolicy(Qt::ActionsContextMenu);
}

       增加鼠标右键的响应事件,添加previewGroupBox->setContextMenuPolicy(Qt::ActionsContextMenu);也可以重载contextMenuEvent函数在其中增加QMenu和信号槽。如下代码所示(未采用)。

 

void Window::contextMenuEvent(QContextMenuEvent*event)
{
    QCursorcur=this->cursor();
    QMenu*menu=newQMenu(this);
    menu->addAction("delete");
    menu->exec(cur.pos());
}

 

7、国际化支持

 

国际化过程:

(1)使用tr()将需要翻译的字符串标记出来,lupdate工具只提取出tr()函数中的相关字符串。

(2)在pro文件中增加一行:TRANSLATIONS += myapp.ts。
(3)pro文件所在的文件夹,然后输入命令lupdate MyApp.pro。

(4)Qt Linguist打开我们的ts文件,然后进行翻译。

(5)lrelease MyApp.pro发布生成myapp.qm文件。

(6)加载myapp.qm文件。

ios 日历 Widget开发 widgetsmith设置日历_字符串_09

 

{ 
    QTranslator translator(0);
    translator.load("calendar.qm",":/");
    app.installTranslator(&translator);
}

有些未实现国际化,window下若乱码,则在window.cpp构造函数中添加:

QTextCodec *codec = QTextCodec::codecForName("utf8");
    QTextCodec::setCodecForLocale(codec);
    QTextCodec::setCodecForCStrings(codec);
    QTextCodec::setCodecForTr(codec);

 

四、总结

 

(1)Qt中的CalendarWidget在Widgets下,相应的说明可以参看其英文文档,其他的部分可以下载源码详细分析。

(2)所用的Qt的库Qt4.6.2,GCC4.4.6 20120305 (Red Hat 4.4.6-4) 。系统是centos6.3。