我正在嘗試構建一個富文本編輯器,它可以使用 Qt 版本 6 呼叫所有常見的富文本格式,例如粗體、斜體和下劃線。在構建了可以正常作業且沒有錯誤的富文本格式化功能之后,我想還構建了一個高級格式檢查器。為了將代碼從 Python 轉換為 C (參見這個問題的答案),我構建了一個函式,該函式位于從QTextEdit.
當我嘗試在沒有除錯的情況下在 Qt Creator IDE 中運行我的代碼時,我發現我撰寫的代碼無法運行并且總是無緣無故地崩潰。
啟用 Qt Creator 的內置除錯器,我看到它說QTextCursor <no such value>and textCursor <no such value>. 但我<QTextCursor>正確地包括在內,并檢查了*.pro檔案(我正在運行qmake)。

它停在 Low Level Debugger 的第二層。

更新:
如果我僅通過回傳來“修復”檢查格式化功能true,則檢查的 QAction 集也會無緣無故地崩潰。看起來很奇怪。
這么煩人的問題。任何幫助將不勝感激。
環境:
作業系統:macOS Big Sur 11.7.1;
型號:運行 64 位 Intel 處理器的 MacBook Air(11 英寸,2013 年中)
x86_64;Qt 版本:6.3.2(Clang 13.0);
Qt Creator 版本:8.0.2;
最小繁殖示例:
主要的。cp :
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.show();
return app.exec();
}
主視窗。小時:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QTextDocument>
#include <QCheckBox>
#include <QTextFrame>
#include <QTextFrameFormat>
#include <QMenuBar>
#include <QMenu>
#include <QMainWindow>
#include <QAction>
#include "Pagination/PagesTextEdit.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void checkFormatting();
private:
QMenuBar* m_menuBar;
QMenu* m_menuFormat;
QAction* m_actionFormatTextBold;
QAction* m_actionFormatTextItalic;
QAction* m_actionFormatTextUnderline;
QTextDocument* doc;
PagesTextEdit* m_paginationWidget;
};
#endif // MAINWINDOW_H
主視窗。cp :
#include "mainwindow.h"
#include <QString>
#include <QScrollBar>
#include <QApplication>
#include <QTextCursor> // <- important
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QMenuBar* m_menuBar;
m_menuBar = new QMenuBar();
this->setMenuBar(m_menuBar);
QMenu* m_menuFormat;
m_menuFormat = new MenuFormat();
m_menuFormat->setText(QString::fromStdString("F&ormat"));
m_menuBar->addMenu(m_menuFormat);
ActionFormatTextBold* m_actionFormatTextBold;
m_actionFormatTextBold = new ActionFormatTextBold(this);
m_menuFormatText->addAction(m_actionFormatTextBold);
ActionFormatTextItalic* m_actionFormatTextItalic;
m_actionFormatTextItalic = new ActionFormatTextItalic(this);
m_menuFormatText->addAction(m_actionFormatTextItalic);
ActionFormatTextUnderline* m_actionFormatTextUnderline;
m_actionFormatTextUnderline = new ActionFormatTextUnderline(this);
m_menuFormatText->addAction(m_actionFormatTextUnderline);
PagesTextEdit* m_paginationWidget;
m_paginationWidget = new PagesTextEdit;
QTextDocument* doc;
doc = new QTextDocument;
doc->setDefaultFont(QFont("Times New Roman", defaultFontSize));
m_paginationWidget->setDocument(doc);
m_paginationWidget->setPageFormat(QPageSize::PageSizeId::A4);
m_paginationWidget->setPageMargins(QMarginsF(20, 20, 20, 20));
m_paginationWidget->setUsePageMode(true);
m_paginationWidget->setPageNumbersAlignment(Qt::AlignHCenter | Qt::AlignTop);
m_paginationWidget->setShowPageNumbers(false);
m_paginationWidget->setTabChangesFocus(false);
m_paginationWidget->setAcceptDrops(true);
m_paginationWidget->setAcceptRichText(true);
setCentralWidget(m_paginationWidget);
connect(m_paginationWidget, &PagesTextEdit::cursorPositionChanged,
this, &MainWindow::checkFormatting);
connect(m_actionFormatTextBold, &QAction::triggered,
m_paginationWidget, &PagesTextEdit::textFormatBold);
connect(m_actionFormatTextItalic, &QAction::triggered,
m_paginationWidget, &PagesTextEdit::textFormatItalic);
connect(m_actionFormatTextUnderline, &QAction::triggered,
m_paginationWidget, &PagesTextEdit::textFormatUnderline);
showMaximized();
}
MainWindow::~MainWindow()
{
}
void MainWindow::checkFormatting() {
bool bold = m_paginationWidget->isBold();
m_actionFormatTextBold->setChecked(bold); // <- m_actionFormatTextBold also crash without checking formatting
}
PagesTextEdit。小時:
#ifndef PAGESTEXTEDIT_H
#define PAGESTEXTEDIT_H
#include <QTextEdit>
#include "PageMetrics.h"
class PagesTextEdit : public QTextEdit
{
Q_OBJECT
public:
explicit PagesTextEdit(QWidget* parent = 0);
void setPageFormat(QPageSize::PageSizeId _pageFormat);
void setPageMargins(const QMarginsF& _margins);
bool usePageMode() const;
bool isBold();
bool isItalic();
bool isUnderline();
public slots:
void textFormatBold(bool isChecked);
void textFormatItalic(bool isChecked);
void textFormatUnderline(bool isChecked);
void setUsePageMode(bool _use);
void setAddSpaceToBottom(bool _addSpace);
void setShowPageNumbers(bool _show);
void setPageNumbersAlignment(Qt::Alignment _align);
protected:
void paintEvent(QPaintEvent* _event);
void resizeEvent(QResizeEvent* _event);
private:
void updateViewportMargins();
void updateVerticalScrollRange();
void paintPagesView();
void paintPageNumbers();
void paintPageNumber(QPainter* _painter, const QRectF& _rect, bool _isHeader, int _number);
private slots:
void aboutVerticalScrollRangeChanged(int _minimum, int _maximum);
void aboutDocumentChanged();
void aboutUpdateDocumentGeometry();
void aboutMergeCharFormat(QTextCharFormat format);
private:
QTextDocument* m_document;
bool m_usePageMode;
bool m_addBottomSpace;
bool m_showPageNumbers;
Qt::Alignment m_pageNumbersAlignment;
PageMetrics m_pageMetrics;
};
#endif // PAGESTEXTEDIT_H
PagesTextEdit。cp :
#include "PagesTextEdit.h"
#include <QAbstractTextDocumentLayout>
#include <QPainter>
#include <QScrollBar>
#include <QTextFrame>
#include <QTextCharFormat>
#include <QTextCursor> // included
PagesTextEdit::PagesTextEdit(QWidget *parent) :
QTextEdit(parent),
m_document(0),
m_usePageMode(false),
m_addBottomSpace(true),
m_showPageNumbers(true),
m_pageNumbersAlignment(Qt::AlignTop | Qt::AlignRight)
{
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
aboutDocumentChanged();
connect(this, SIGNAL(textChanged()), this, SLOT(aboutDocumentChanged()));
connect(verticalScrollBar(), SIGNAL(rangeChanged(int,int)),
this, SLOT(aboutVerticalScrollRangeChanged(int,int)));
setLineWrapMode(QTextEdit::LineWrapMode::WidgetWidth);
}
void PagesTextEdit::setPageFormat(QPageSize::PageSizeId _pageFormat) {
m_pageMetrics.update(_pageFormat);
repaint();
}
void PagesTextEdit::setPageMargins(const QMarginsF& _margins) {
m_pageMetrics.update(m_pageMetrics.pageFormat(), _margins);
repaint();
}
bool PagesTextEdit::usePageMode() const {
return m_usePageMode;
}
void PagesTextEdit::setUsePageMode(bool _use) {
if (m_usePageMode != _use) {
m_usePageMode = _use;
repaint();
}
}
void PagesTextEdit::setAddSpaceToBottom(bool _addSpace) {
if (m_addBottomSpace != _addSpace) {
m_addBottomSpace = _addSpace;
repaint();
}
}
void PagesTextEdit::setShowPageNumbers(bool _show) {
if (m_showPageNumbers != _show) {
m_showPageNumbers = _show;
repaint();
}
}
void PagesTextEdit::setPageNumbersAlignment(Qt::Alignment _align) {
if (m_pageNumbersAlignment != _align) {
m_pageNumbersAlignment = _align;
repaint();
}
}
void PagesTextEdit::paintEvent(QPaintEvent* _event) {
updateVerticalScrollRange();
paintPagesView();
paintPageNumbers();
QTextEdit::paintEvent(_event);
}
void PagesTextEdit::resizeEvent(QResizeEvent* _event) {
updateViewportMargins();
updateVerticalScrollRange();
QTextEdit::resizeEvent(_event);
}
void PagesTextEdit::updateViewportMargins() {
QMargins viewportMargins;
if (m_usePageMode) {
int pageWidth = m_pageMetrics.pxPageSize().width();
int pageHeight = m_pageMetrics.pxPageSize().height();
const int DEFAULT_TOP_MARGIN = 20;
const int DEFAULT_BOTTOM_MARGIN = 20;
{
int leftMargin = 0;
int rightMargin = 0;
if (width() > pageWidth) {
const int BORDERS_WIDTH = 4;
const int VERTICAL_SCROLLBAR_WIDTH =
verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0;
leftMargin = rightMargin =
(width() - pageWidth - VERTICAL_SCROLLBAR_WIDTH - BORDERS_WIDTH) / 2;
}
int topMargin = DEFAULT_TOP_MARGIN;
int bottomMargin = DEFAULT_BOTTOM_MARGIN;
int documentHeight = pageHeight * document()->pageCount();
if ((height() - documentHeight) > (DEFAULT_TOP_MARGIN DEFAULT_BOTTOM_MARGIN)) {
const int BORDERS_HEIGHT = 2;
const int HORIZONTAL_SCROLLBAR_HEIGHT =
horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0;
bottomMargin =
height() - documentHeight - HORIZONTAL_SCROLLBAR_HEIGHT - DEFAULT_TOP_MARGIN - BORDERS_HEIGHT;
}
viewportMargins = QMargins(leftMargin, topMargin, rightMargin, bottomMargin);
}
}
setViewportMargins(viewportMargins);
aboutUpdateDocumentGeometry();
}
void PagesTextEdit::updateVerticalScrollRange() {
if (m_usePageMode) {
const int pageHeight = m_pageMetrics.pxPageSize().height();
const int documentHeight = pageHeight * document()->pageCount();
const int maximumValue = documentHeight - viewport()->height();
if (verticalScrollBar()->maximum() != maximumValue) {
verticalScrollBar()->setMaximum(maximumValue);
}
}
else {
const int SCROLL_DELTA = 800;
int maximumValue =
document()->size().height() - viewport()->size().height()
(m_addBottomSpace ? SCROLL_DELTA : 0);
if (verticalScrollBar()->maximum() != maximumValue) {
verticalScrollBar()->setMaximum(maximumValue);
}
}
}
void PagesTextEdit::paintPagesView() {
if (m_usePageMode) {
qreal pageWidth = m_pageMetrics.pxPageSize().width();
qreal pageHeight = m_pageMetrics.pxPageSize().height();
QPainter p(viewport());
QPen spacePen(palette().window(), 9);
QPen borderPen(palette().dark(), 1);
qreal curHeight = pageHeight - (verticalScrollBar()->value() % (int)pageHeight);
const int x = pageWidth (width() % 2 == 0 ? 2 : 1);
const int horizontalDelta = horizontalScrollBar()->value();
if (curHeight - pageHeight >= 0) {
p.setPen(borderPen);
p.drawLine(0, curHeight - pageHeight, x, curHeight - pageHeight);
}
while (curHeight <= height()) {
p.setPen(spacePen);
p.drawLine(0, curHeight-4, width(), curHeight-4);
p.setPen(borderPen);
p.drawLine(0, curHeight-8, x, curHeight-8);
p.drawLine(0, curHeight, x, curHeight);
p.drawLine(0 - horizontalDelta, curHeight - pageHeight, 0 - horizontalDelta, curHeight - 8);
p.drawLine(x - horizontalDelta, curHeight - pageHeight, x - horizontalDelta, curHeight - 8);
curHeight = pageHeight;
}
if (curHeight >= height()) {
p.setPen(borderPen);
p.drawLine(0 - horizontalDelta, curHeight-pageHeight, 0 - horizontalDelta, height());
p.drawLine(x - horizontalDelta, curHeight-pageHeight, x - horizontalDelta, height());
}
}
}
void PagesTextEdit::paintPageNumbers() {
if (m_usePageMode && !m_pageMetrics.pxPageMargins().isNull() && m_showPageNumbers) {
QSizeF pageSize(m_pageMetrics.pxPageSize());
QMarginsF pageMargins(m_pageMetrics.pxPageMargins());
QPainter p(viewport());
p.setFont(document()->defaultFont());
p.setPen(QPen(palette().text(), 1));
qreal curHeight = pageSize.height() - (verticalScrollBar()->value() % (int)pageSize.height());
qreal leftMarginPosition = pageMargins.left() - horizontalScrollBar()->value();
qreal marginWidth = pageSize.width() - pageMargins.left() - pageMargins.right();
int pageNumber = verticalScrollBar()->value() / pageSize.height() 1;
if (curHeight - pageMargins.top() >= 0) {
QRectF topMarginRect(leftMarginPosition, curHeight - pageSize.height(), marginWidth, pageMargins.top());
paintPageNumber(&p, topMarginRect, true, pageNumber);
}
while (curHeight < height()) {
QRect bottomMarginRect(leftMarginPosition, curHeight - pageMargins.bottom(), marginWidth, pageMargins.bottom());
paintPageNumber(&p, bottomMarginRect, false, pageNumber);
pageNumber;
QRect topMarginRect(leftMarginPosition, curHeight, marginWidth, pageMargins.top());
paintPageNumber(&p, topMarginRect, true, pageNumber);
curHeight = pageSize.height();
}
}
}
void PagesTextEdit::paintPageNumber(QPainter* _painter, const QRectF& _rect, bool _isHeader, int _number) {
if (_isHeader) {
if (m_pageNumbersAlignment.testFlag(Qt::AlignTop)) {
_painter->drawText(_rect, Qt::AlignVCenter | (m_pageNumbersAlignment ^ Qt::AlignTop),
QString::number(_number));
}
}
else {
if (m_pageNumbersAlignment.testFlag(Qt::AlignBottom)) {
_painter->drawText(_rect, Qt::AlignVCenter | (m_pageNumbersAlignment ^ Qt::AlignBottom),
QString::number(_number));
}
}
}
void PagesTextEdit::aboutVerticalScrollRangeChanged(int _minimum, int _maximum) {
Q_UNUSED(_minimum);
updateViewportMargins();
int scrollValue = verticalScrollBar()->value();
if (scrollValue > _maximum) {
updateVerticalScrollRange();
}
}
void PagesTextEdit::aboutDocumentChanged() {
if (m_document != document()) {
m_document = document();
connect(document()->documentLayout(), SIGNAL(update()), this, SLOT(aboutUpdateDocumentGeometry()));
}
}
void PagesTextEdit::aboutUpdateDocumentGeometry() {
QSizeF documentSize(width() - verticalScrollBar()->width(), -1);
if (m_usePageMode) {
int pageWidth = m_pageMetrics.pxPageSize().width();
int pageHeight = m_pageMetrics.pxPageSize().height();
documentSize = QSizeF(pageWidth, pageHeight);
}
if (document()->pageSize() != documentSize) {
document()->setPageSize(documentSize);
}
if (document()->documentMargin() != 0) {
document()->setDocumentMargin(0);
}
QMarginsF rootFrameMargins = m_pageMetrics.pxPageMargins();
QTextFrameFormat rootFrameFormat = document()->rootFrame()->frameFormat();
if (rootFrameFormat.leftMargin() != rootFrameMargins.left()
|| rootFrameFormat.topMargin() != rootFrameMargins.top()
|| rootFrameFormat.rightMargin() != rootFrameMargins.right()
|| rootFrameFormat.bottomMargin() != rootFrameMargins.bottom()) {
rootFrameFormat.setLeftMargin(rootFrameMargins.left());
rootFrameFormat.setTopMargin(rootFrameMargins.top());
rootFrameFormat.setRightMargin(rootFrameMargins.right());
rootFrameFormat.setBottomMargin(rootFrameMargins.bottom());
document()->rootFrame()->setFrameFormat(rootFrameFormat);
}
}
void PagesTextEdit::aboutMergeCharFormat(QTextCharFormat format) {
// no problem
QTextCursor cur = textCursor();
if (!cur.hasSelection()) {
cur.select(QTextCursor::SelectionType::WordUnderCursor);
}
cur.mergeCharFormat(format);
}
void PagesTextEdit::textFormatBold(bool isChecked) {
// no problem
QTextCharFormat form;
if (isChecked) {
int weight = QFont::Bold;
form.setFontWeight(weight);
} else {
int weight = QFont::Normal;
form.setFontWeight(weight);
}
aboutMergeCharFormat(form);
}
void PagesTextEdit::textFormatItalic(bool isChecked) {
// no problem
QTextCharFormat form;
if (isChecked) {
bool italic = true;
form.setFontItalic(italic);
} else {
bool italic = false;
form.setFontItalic(italic);
}
aboutMergeCharFormat(form);
}
void PagesTextEdit::textFormatUnderline(bool isChecked) {
// no problem
QTextCharFormat form;
if (isChecked) {
bool underline = true;
form.setFontUnderline(underline);
} else {
bool underline = false;
form.setFontUnderline(underline);
}
aboutMergeCharFormat(form);
}
bool PagesTextEdit::isBold() {
bool bold = false;
QTextCursor cursor = textCursor(); // problem here
// Refer to the pictures...
// QTextCursor: <no such value>
// textCursor: <no such value>
// BUT I truthly included ALL the QTextCursors and QTextEdits in above
if (cursor.hasSelection()) {
int selectionStart = (cursor.selectionStart() 1);
int selectionEnd = (cursor.selectionEnd() 1);
for (int pos = selectionStart; pos < selectionEnd; pos ) {
cursor.setPosition(pos);
QTextCharFormat form = cursor.charFormat();
if (form.fontWeight() >= QFont::Bold) {
bold = true;
} else {
bold = false;
break;
}
}
} else {
bold = (cursor.charFormat().fontWeight() >= QFont::Bold);
}
return bold;
}
任何建議將不勝感激!!!謝謝!
uj5u.com熱心網友回復:
讓我看看你的代碼...
此代碼與物件繼承無關,而是與標頭/源代碼控制有關。利用
//directly without using such useless shadow declarations
m_menuFormat = new QMenu(this);
m_menuFormat->setTitle('format');
m_menuBar->addMenu(m_menuFormat);
代替
//go ahead with python or java but don't trouble cpp
MenuFormat m_menuFormat;
//unless u want to see 15:49:26: /Users/Scott/Documents/test/test.app/Contents/MacOS/test crashed.
m_menuFormat = ...;
...;
雖然必須確保 m_menuFormat 出現在頭檔案串列中。
別緊張。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/531681.html
