Qt: делаем календарь в таблице QTextTable
Вообще-то в Qt5 есть готовый виджет Calendar
, котрый можно кинуть на форму, созданную на основе QWidget
, затем щелкнуть по форме вне виджета
, нажать Ctrl+H, чтобы его растянуть по форме, потом нажать Ctrl+R - и приложение готово:
Увы, табличку в документ Word отсюда не скопируешь, да и непонятно, как не показывать дни соседнего месяца в первой или последней неделе текущего.
Намного ли сложнее сделать такое вручную? Давайте попробуем, заодно посмотрев полезные приёмы работы с таблицей QTextTable
, её ячейками QTextTableCell
и форматами QTextCharFormat
, QTextBlockFormat
(полный аналог - форматы строчного и блочного элементов HTML). Да и вообще, логика работы с таблицей QTextTable
такая же, как с разметкой HTML.
Таблицу мы делаем просто из ячеек с цифрами, её можно будет выделить, скопировать, и затем вставить в тот же Word.
Виджет основан на QMainWindow
, описание класса очень просто (файл mainwindow.h
):
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QDate> #include <QMainWindow> class QTextBrowser; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); public slots: void setFontSize(int size); //выбор шрифта void setMonth(int month); //выбор месяца void setYear(QDate date); //выбор года private: void insertCalendar(); int fontSize; QDate selectedDate; QTextBrowser *editor; }; #endif
Основные действия в реализации класса mainwindow.cpp
закомментированы:
#include <QtWidgets> #include "mainwindow.h" MainWindow::MainWindow() { //конструктор selectedDate = QDate::currentDate(); fontSize = 10; QWidget *centralWidget = new QWidget; QLabel *dateLabel = new QLabel(tr("Дата:")); QComboBox *monthCombo = new QComboBox; for (int month = 1; month <= 12; ++month) monthCombo->addItem(QDate::longMonthName(month)); QDateTimeEdit *yearEdit = new QDateTimeEdit; yearEdit->setDisplayFormat("yyyy"); yearEdit->setDateRange (QDate(1918, 1, 1), QDate(9998, 1, 1)); monthCombo->setCurrentIndex (selectedDate.month() - 1); yearEdit->setDate (selectedDate); QLabel *fontSizeLabel = new QLabel(tr("Шрифт:")); QSpinBox *fontSizeSpinBox = new QSpinBox; fontSizeSpinBox->setRange(6, 72); fontSizeSpinBox->setValue(10); editor = new QTextBrowser; //компонента для календаря insertCalendar(); //главный метод connect(monthCombo, SIGNAL(activated(int)), this, SLOT(setMonth(int))); connect(yearEdit, SIGNAL(dateChanged(QDate)), this, SLOT(setYear(QDate))); connect(fontSizeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setFontSize(int))); QHBoxLayout *horizontalLayout = new QHBoxLayout; //панель навигации horizontalLayout->addWidget(dateLabel); horizontalLayout->addWidget(monthCombo); horizontalLayout->addWidget(yearEdit); horizontalLayout->addSpacing(20); horizontalLayout->addWidget(fontSizeLabel); horizontalLayout->addWidget(fontSizeSpinBox); horizontalLayout->addStretch(1); QVBoxLayout *centralLayout = new QVBoxLayout; centralLayout->addLayout(horizontalLayout); centralLayout->addWidget(editor, 1); centralWidget->setLayout(centralLayout); setCentralWidget(centralWidget); } void MainWindow::insertCalendar() { editor->clear(); //очистить QTextCursor cursor = editor->textCursor(); cursor.beginEditBlock(); //создать курсор и поставить в начало QDate date(selectedDate.year(), selectedDate.month(), 1); //создать дату - 1-е число выбранного в панели месяца QTextTableFormat tableFormat; //создать формат таблицы tableFormat.setAlignment(Qt::AlignHCenter); //выравнивание tableFormat.setBackground(QColor("#EEEEEE")); //фоновый цвет tableFormat.setCellPadding(4); //отступ от края ячейки tableFormat.setCellSpacing(0); //промежуток между ячейками QVector <QTextLength> constraints; //7 столбцов по 15% шириной constraints << QTextLength(QTextLength::PercentageLength, 15) << QTextLength(QTextLength::PercentageLength, 15) << QTextLength(QTextLength::PercentageLength, 15) << QTextLength(QTextLength::PercentageLength, 15) << QTextLength(QTextLength::PercentageLength, 15) << QTextLength(QTextLength::PercentageLength, 15) << QTextLength(QTextLength::PercentageLength, 15); tableFormat.setColumnWidthConstraints(constraints); QTextTable *table = cursor.insertTable(1, 7, tableFormat); //создать таблицу из 1 строки и 7 описанных выше столбцов QTextCharFormat format = cursor.charFormat(); //общий формат format.setFontPointSize(fontSize); //поставить размер шрифта QTextCharFormat boldFormat = format; boldFormat.setFontWeight(QFont::Bold); //жирный QTextCharFormat highlightedFormat = boldFormat; highlightedFormat.setBackground(Qt::yellow); //подсвеченный жёлтым QTextBlockFormat centerAlignment; //равнять по центру centerAlignment.setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); QTextBlockFormat rightAlignment; //равнять направо rightAlignment.setAlignment(Qt::AlignRight); for (int weekDay = 0; weekDay < 7; weekDay++) { //подписи дней недели QTextTableCell cell = table->cellAt(0, weekDay); //в нулевой строке QTextCursor cellCursor = cell.firstCursorPosition(); cellCursor.setBlockFormat(centerAlignment); cellCursor.insertText(QString("%1"). arg(QDate::longDayName(weekDay+1)),boldFormat); } table->insertRows(table->rows(), 1); //вставить подписи while (date.month() == selectedDate.month()) { //для текущего месяца int weekDay = date.dayOfWeek(); //1=Пн, ..., 7 =Вс QTextTableCell cell = table->cellAt(table->rows()-1, weekDay-1); QTextCursor cellCursor = cell.firstCursorPosition(); cellCursor.setBlockFormat(rightAlignment); //текущую дату - желтым, иначе обычным if (date == QDate::currentDate()) cellCursor.insertText(QString("%1").arg(date.day()), highlightedFormat); else cellCursor.insertText(QString("%1").arg(date.day()), format); date = date.addDays(1); //следующий день if (weekDay == 7 && date.month() == selectedDate.month()) table->insertRows(table->rows(), 1); //добавить строчку, если пора } cursor.endEditBlock(); //завершить редактирование setWindowTitle(tr("Календарь на %1 %2"). //титул окна arg(QDate::longMonthName(selectedDate.month())). arg(selectedDate.year())); } void MainWindow::setFontSize(int size) { fontSize = size; insertCalendar(); } void MainWindow::setMonth(int month) { selectedDate = QDate(selectedDate.year(), month + 1, selectedDate.day()); insertCalendar(); } void MainWindow::setYear(QDate date) { selectedDate = QDate(date.year(), selectedDate.month(), selectedDate.day()); insertCalendar(); }
Вот что вышло. Это можно масштабировать и т.д.
вид окна приложения
Скачать этот пример в архиве .zip с проектом Qt 5.X (4 Кб)
06.04.2016, 12:54 [11400 просмотров]