[QT] Notas portátiles de Qt (actualizadas continuamente...)

Tabla de contenido

Qt obtiene la ruta del escritorio de la computadora actual

#include <QStandardPaths>
QString desktop_path = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);

Qt obtiene la ruta de ejecución del programa actual

#include <QCoreApplication>

//方法1:
QString fileName = QCoreApplication::applicationDirPath();

//方法2:
QString fileName = QApplication::applicationDirPath();

La diferencia entre QCoreApplication y QApplication:
QApplication hereda de QGuiApplication y QGuiApplication hereda de QCoreApplication
QApplication: con Gui, QCoreApplication: sin Gui

Qt crea un nuevo archivo de texto txt y escribe el contenido

//在当前程序运行路径下创建
QFile file(QCoreApplication::applicationDirPath() + "/test.txt");
if (!file.exists()) {
    
    
    qDebug() << "文件不存在!";
}
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
    
    
    qDebug() << "文件打开失败!";
}
QString str = "测试文件是否被修改!";
QTextStream out(&file);
out << str;  //将str写入文件
file.close();

Cómo escribir contenido en QPlainTextEdit

void insertPlainText(const QString &text);

void appendPlainText(const QString &text);

Temporizador Q

QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &MainWindow::slotRefresh());
timer->start(1000);  //延迟1秒刷新

QTimer también proporciona una función estática para temporizadores de un solo uso. Por ejemplo:

QTimer::singleShot(200, this, &MainWindow::slotRefresh());

Uso de QMessageBox

Constructor

QMessageBox messageBox(QMessageBox::Question, "Question", "The current project has been modified.\nDo you want to save it?", QMessageBox::Yes | QMessageBox::No);
messageBox.exec();

Implementado a través de constructores y funciones de propiedad.

QMessageBox messageBox(this);
messageBox.setIcon(QMessageBox::Warning);
messageBox.setWindowTitle("Warning");
messageBox.setText("Parsed file not found! Please reconfigure!");
messageBox.setStandardButtons(QMessageBox::Yes|QMessageBox::No);
messageBox.setDefaultButton(QMessageBox::Yes);
messageBox.exec();

función estática

QMessageBox::Information(this, "Information", "Project saved successfully!");

QLatin1String

QLatin1String es una envoltura delgada alrededor de const char*.

Muchas funciones miembro de QString se sobrecargan utilizando const char* en lugar de QString como parámetro.
Insertar descripción de la imagen aquí

Por ejemplo, suponiendo que str es un objeto QString,

if (str == "auto" || str == "extern"
        || str == "static" || str == "register") {
    
    
    ...
}

El código anterior se ejecutará mucho más rápido que el siguiente código

if (str == QString("auto") || str == QString("extern")
        || str == QString("static") || str == QString("register")) {
    
    
    ...
}

Porque en la segunda parte del código, se construirán cuatro objetos QString temporales y se copiarán los valores de la cadena.

Si utiliza la clase QLatin1String para escribir el programa anterior, es

if (str == QLatin1String("auto")
        || str == QLatin1String("extern")
        || str == QLatin1String("static")
        || str == QLatin1String("register") {
    
    
    ...
}

Aunque el código es un poco largo para ingresar, su eficiencia de ejecución es la misma que la del primer código anterior.

QLatin1String se puede utilizar en cualquier lugar donde se espere un objeto QString

QLabel label;
label.setObjectName(QLatin1String("111"));

Diseño Q

void QLayout::setContentsMargins(int left, int top, int right, int bottom)

Establezca los márgenes izquierdo, superior, derecho e inferior para utilizarlos en el diseño.
De forma predeterminada, QLayout usa el valor proporcionado por el estilo. En la mayoría de las plataformas, los márgenes son de 11 píxeles en todas las direcciones.

QGridLayout* grid = findChild<QGridLayout*>("gridLayout");  //通过对象名获取布局
grid->setContentsMargins(10, 30, 50, 70);  //上、左、右、下

Insertar descripción de la imagen aquí

int spacing() const
void setSpacing(int)

Establece el espaciado entre widgets en un diseño.
Si un valor no se establece explícitamente, el espaciado del diseño se hereda del diseño principal o de la configuración de estilo del widget principal.
Para QGridLayout y QFormLayout, puede usar setHorizontalSpacing() y setVerticalSpacing() para establecer diferentes espacios horizontales y verticales. En este caso, el espaciado() devuelve -1

C++

¿Cuál es la diferencia entre escribir el archivo de encabezado de clase #include en el archivo de encabezado de C++ y escribir directamente la clase más el nombre de la clase?

El nombre de la clase de clase solo declara que dicha clase existe, pero no se puede obtener información específica sobre esta clase a través de esta declaración. De esta forma puedes declarar un puntero de este tipo en otros lugares donde se use.

#include "xx.h" expande directamente el archivo xx.h durante la compilación, por lo que se pueden usar las interfaces internas y se pueden declarar objetos. Pero la clase xx; no funciona de esta manera. Solo puedes usar su puntero o referencia y no puedes crear un objeto declarado.

使用class 类名一般是为了去除编译依赖,减少编译消耗的时间。
Por ejemplo:
hay un archivo de encabezado "common.h", lo necesita en todos los archivos de encabezado, así que #include "common.h", cuando hay algunos cambios en el código en common.h, está ejecutando el código. todos los archivos de encabezado que dependen de él deben volver a compilarse. Y si es Clase Común, cuando se realizan algunos cambios en el código en common.h, cuando ejecuta el código, todos los archivos de encabezado que dependen de él no se compilarán nuevamente después de haberlo compilado una vez antes. (Después de compilar el encabezado de un archivo, si el archivo de encabezado no se ha modificado, no se volverá a compilar la próxima vez que se ejecute el código)

Solo declarar clases sin incluir puede reducir la correlación de cada archivo durante la compilación. Al cambiar algunas clases, no provocará la recompilación de una gran cantidad de otros archivos. No hace ninguna diferencia cuando se trabaja en un proyecto pequeño, pero sí cuando es más grande. La ventaja de esto se hace evidente cuando la compilación lleva varias horas seguidas.

palabra clave mutable

Mutable también está configurado para romper las limitaciones de const. Las variables modificadas por mutable siempre estarán en un estado mutable, incluso en una función constante
.

declaración anticipada

Declarar una clase en un archivo de encabezado de clase sin definirla se llama declaración directa.
La clase A declarada hacia adelante en el archivo de encabezado es un tipo incompleto. Solo conocemos el tipo de clase A, pero no sabemos qué miembros contiene la clase A.
Un tipo incompleto no puede definir un objeto del tipo, pero solo puede usarse para definir un puntero o referencia del tipo, o para declarar una función del tipo como parámetro o valor de retorno.
Beneficio: el tiempo de compilación se puede reducir para #includes innecesarios

// 当使用前向引用声明时,只能使用被声明的符号,而不能涉及类的任何细节。
class A;  //前向声明类A
class B{
    
    
public
	A* m_a;  //用于定义指向这个类型的指针或引用
	void func(A a);  //用于声明(不是定义)使用该类型作为形参或者返回类型的函数
}
  1. Una clase declarada hacia adelante no puede definir objetos (el tamaño y los miembros internos de la clase no se conocen y no se pueden crear instancias).

  2. Se puede utilizar para definir punteros y referencias a este tipo (es decir, definir punteros o referencias de esta clase como variables miembro).

  3. Se puede utilizar para declarar (no definir) funciones que utilizan este tipo como parámetro formal o tipo de retorno.

QFuente

La clase QFont se utiliza para dibujar fuentes de texto.
Tenga en cuenta que debe existir una instancia de QGuiApplication antes de usar QFont. La fuente predeterminada de la aplicación se puede configurar usando QGuiApplication::setFont().
Si la fuente seleccionada no contiene todos los caracteres que deben mostrarse, QFont intentará encontrar los caracteres en la fuente equivalente más cercana.
Cuando QPainter dibuja un carácter de una fuente, QFont informará si tiene ese carácter; de lo contrario, QPainter dibujará un cuadrado sin relleno.
Constructores de uso común

QFont(const QString &family, int pointSize = -1, int weight = -1, bool italic = false);
//参数说明:字体样式、字体大小、字体粗细、是否斜体

Funciones de uso común

void setFamily(const QString &family)//设置字体样式

void setPointSize(int pointSize)//设置字体大小 

void setWeight(int weight)//设置字体粗细

void setBold(bool enable)//设置字体是否加粗

void setItalic(bool enable)//设置字体是否斜体

void setPixelSize(int pixelSize)//设置字体像素大小

void setOverline(bool enable)//设置字体上划线

void setUnderline(bool enable)//设置字体下划线

void setStrikeOut(bool enable)//设置字体删除线
void setLetterSpacing(SpacingType type, qreal spacing);
//将字体的字母间距设置为spacing,并将间距的类型设置为type。
//字母间距改变字体中单个字母之间的默认间距。根据所选择的间距类型,字母之间的间距可以按字符宽度的百分比或按像素的百分比设置为更小或更大。

enum QFont::SpacingType

enumerar valor describir
QFont::Porcentaje de espaciado 0 Un valor de 100 dejará el espacio sin cambios; un valor de 200 ampliará el espacio detrás de los caracteres al ancho de los propios caracteres.
QFont::Espaciado absoluto 1 Los valores positivos aumentan el espaciado entre letras en los píxeles correspondientes; los valores negativos disminuyen el espaciado.
void setCapitalization(Capitalization caps);
//将此字体的文本的大写设置为大写。
//字体的大写使文本以选定的大写模式显示。

enum QFont::Capitalization

enumerar valor describir
QFont::Mezcla de mayúsculas y minúsculas 0 Opción de representación de texto normal donde no se aplican cambios de mayúsculas y minúsculas.
QFont::Todos en mayúsculas 1 todas las mayúsculas
QFont::Todos en minúsculas 2 todo en minúsculas
QFont::SmallCaps 3 Versalitas significa todas las letras mayúsculas, pero tienen el mismo tamaño que las minúsculas.
QFont::Capitalizar 4 Poner en mayúscula la primera letra

Etiqueta Q

Establecer el tamaño y el color de fuente QLabel

QLabel* label = new QLabel(tr("test"));
font.setFont(QFont("宋体"), 12);

QPalette pa;
pa.setColor(QPalette::WindowText, Qt::red);
font.setPalette(pa);

QLabel establece el color de fondo

	QLabel* colorLabel = new QLabel(this);
    colorLabel->setFixedSize(10, 10);
    QPalette palette = colorLabel->palette();
    palette.setColor(QPalette::Background, Qt::black);
    colorLabel->setAutoFillBackground(true);
    colorLabel->setPalette(palette);

La fuente excede la longitud de QLabel, cómo mostrarla en forma de puntos suspensivos

QLabel* m_activeText = new QLabel(this);
QString text = "abcdefg";
QFontMetrics fontWidth(m_activeText->font());  //计算字体的宽度
QString elideText = fontWidth.elidedText(text, Qt::ElideMiddle, 80);  //80为最大宽度
m_activeText->setText(elideText);

QLabel no se muestra completamente, ¿cómo ajustar la línea automáticamente?

label->setWordWrap(true);                     // true:自动换行
label->setAlignment(Qt::AlignVCenter);        // 对齐方式

Cómo agregar líneas divisorias al diseño

QLabel* lineLabel = new QLabel(this);
lineLabel->setFrameStyle(QFrame::HLine | QFrame::Sunken);  //Sunken:凹陷,Raised:凸起

Simplemente agregue lineLabel al diseño.

Se puede hacer clic en el enlace mostrado por Qlabel para abrirlo.

label->setTextInteractionFlags(Qt::TextBrowserInteraction);  //label中的内容可用鼠标选择文本复制,链接激活
label->setOpenExternalLinks(true);                           //label中的内容若为链接,可直接点击打开
label.setText("<a href = https://blog.csdn.net/WL0616?spm=1000.2115.3001.5343>点我试试");   //https://blog.csdn.net/WL0616?spm=1000.2115.3001.5343为链接网址

Obtenga el botón actualmente presionado en la interfaz

 QPushButton* btn= qobject_cast<QPushButton*>(sender());

qobject_cast

La función qobject_cast() se comporta como la función Dynamic_cast() de C++ estándar, con la ventaja de que no requiere soporte RTTI y puede funcionar a través de los límites de la biblioteca dinámica.
qobject_cast convierte dinámicamente el tipo de la clase QObject.qobject_cast convierte el tipo entre paréntesis () al tipo entre paréntesis angulares <>.
T qobject_cast(QObject *object)Existen dos limitaciones a la hora de utilizarlo:

  1. El tipo T devuelto debe heredar de QObject.
  2. La macro Q_OBJECT debe incluirse en la declaración.
QLabel* label = new QLabel();
QWidget* widget = qobject_cast<QWidget*>(label);

QDiálogo

QDialog ocultar/eliminar barra de título

setWindowFlags(Qt::FramelessWindowHint);

Genera una ventana sin bordes. Los usuarios no pueden mover ni cambiar el tamaño de ventanas sin bordes a través del sistema de ventanas.

QDialog elimina el signo de interrogación y solo lo mantiene cerrado

Qt::WindowFlags flags = Qt::Dialog;
flags |= Qt::WindowCloseButtonHint;
setWindowFlags(flags);

Cómo quitar el marco punteado de un botón

Por ejemplo: un botón tiene un efecto de enfoque ¿
Insertar descripción de la imagen aquí
Cómo cancelar este efecto?

//方法1
setFocusPolicy(Qt::NoFocus);

//方法2
setStyleSheet("outline: none");  

//方法3
setStyleSheet("padding: -1"); 

QPushButton establece el tamaño del botón

QPushButton hereda de QAbstractButton y QAbstractButton hereda de QWidget. La siguiente es en realidad la interfaz de QWidget.

void setMinimumHeight(int minh)
void setMinimumSize(const QSize &)
void setMinimumSize(int minw, int minh)
void setMinimumWidth(int minw)

Explicación detallada del cuarto parámetro de rgba(0,0,0,0)

Los primeros tres parámetros indican el color y el cuarto parámetro indica la transparencia, su rango está entre 0.0 y 1.0, y 0.5 es translúcido.
rgba(0,0,0,1) significa negro completamente opaco;
rgba(0,0,0,0.5) significa semitransparente, que parece gris;
rgba(0,0,0,0) significa blanco completamente opaco, que es, incoloro;

QT implementa desvanecimiento de fondo después de una ventana emergente

QWidget* widget = nuevo QWidget(este);
widget->resize(this->width(), this->height());
widget->mover(0, 0);
widget->setStyleSheet(“color de fondo:rgba(0, 0, 0, 0.3);”);
widget->mostrar();

La diferencia entre geometría() y frameGeometry()

geometría(): tamaño de la interfaz, excluyendo el decorador de la ventana (es decir, la barra de título)
frameGeometry(): tamaño de la interfaz, incluido el decorador de la ventana superior (es decir, la barra de título)

Sistema de propiedades Qt Q_PROPERTY

Qt proporciona un maravilloso sistema de propiedades. Q_PROPERTY() es una macro utilizada para declarar una propiedad en una clase.
Una propiedad se comporta como un miembro de datos de una clase, pero tiene una funcionalidad adicional a la que se accede a través del sistema de metaobjetos .

Q_PROPERTY(type name
           (READ getFunction [WRITE setFunction] |
            MEMBER memberName [(READ getFunction | WRITE setFunction)])
           [RESET resetFunction]
           [NOTIFY notifySignal]
           [REVISION int]
           [DESIGNABLE bool]
           [SCRIPTABLE bool]
           [STORED bool]
           [USER bool]
           [CONSTANT]
           [FINAL])

Ejemplo de propiedad:

 Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)

Q_PROPERTY: macro utilizada para declarar atributos, bool especificado por Qt
: tipo de atributo
habilitado: nombre del atributo
READ isEnabled (estas dos palabras se pueden entender juntas): es decir, el valor del atributo se puede leer a través de isEnabled
WRITE setEnabled (estas dos palabras Puede juntarlos para entender): es decir, puede establecer el valor del atributo a través de setEnabled

Lo anterior es solo un atributo y una declaración, pero en realidad no está implementado. También es necesario implementar isEnabled y setEnabled respectivamente, para que todo el atributo pueda usarse realmente.

ejemplo:

class MaskWidget : public QDialog {
    
    
    Q_OBJECT
    Q_PROPERTY(QStringList names READ names WRITE setNames DESIGNABLE true)
public:
    static MaskWidget* instance();
    void setMainWidget(QWidget* pWidget);

    QStringList names() const;
    void setNames(const QStringList& names);
	...
};

Significados de campos adicionales proporcionados por los atributos

LEER: Se utiliza para leer valores de atributos. Si no se especifica la variable miembro (a través de MIEMBRO), se requiere una función de acceso de lectura.

ESCRITURA: Las funciones de acceso de escritura son opcionales. Se utiliza para establecer valores de atributos. Debe devolver void y debe aceptar solo un argumento, ya sea el tipo de propiedad o un puntero o referencia a ese tipo.

MIEMBRO: Si no se especifica ninguna función de acceso de lectura, se requiere asociación de variable miembro. Esto hace que una variable miembro determinada sea legible y escribible sin la necesidad de crear funciones de acceso de lectura y escritura. Si necesita controlar el acceso a variables, puede usar funciones de acceso de lectura o escritura además de la asociación de variables miembro (pero no ambas).

RESET: La función de reinicio es opcional. Se utiliza para restablecer una propiedad a su valor predeterminado específico del contexto.

NOTIFICAR: Las señales de notificación son opcionales. Si se define, debe especificar una señal existente en la clase que se emite cuando cambia el valor de la propiedad. Las señales de notificación para variables miembro deben tomar cero o un argumento, que debe ser del mismo tipo que la propiedad. El parámetro tomará el nuevo valor de la propiedad. La señal NOTIFY solo debe emitirse cuando la propiedad realmente haya cambiado, para evitar que los enlaces se vuelvan a calcular innecesariamente en QML.

REVISIÓN: El número de revisión es opcional. Si se incluye, definirá las propiedades y sus señales de notificación para su uso en una versión específica de la API (generalmente para exposición a QML). Si no se incluye, el valor predeterminado es 0.

DISEÑABLE: Indica si la propiedad debe ser visible en el editor de propiedades de una herramienta de diseño GUI (por ejemplo, Qt Designer). La mayoría de las propiedades se pueden diseñar (el valor predeterminado es verdadero). Se pueden especificar funciones miembro booleanas en lugar de verdadero o falso.

SCRIPTABLE: Indica si el motor de script debe acceder a esta propiedad (el valor predeterminado es verdadero). Se pueden especificar funciones miembro booleanas en lugar de verdadero o falso.

ALMACENADO: Indica si el atributo debe considerarse independiente o dependiente de otros valores. También indica si el valor de la propiedad debe guardarse al almacenar el estado del objeto.

USUARIO: Indica si la propiedad está designada como una propiedad de la clase orientada al usuario o una propiedad editable por el usuario. Normalmente, sólo hay un atributo de usuario por clase (el valor predeterminado es falso).

CONSTANTE: Indica que el valor del atributo es una constante. Para una instancia de objeto determinada, el método READ de una propiedad constante debe devolver el mismo valor cada vez que se llama. El valor de esta constante puede diferir para diferentes instancias del objeto. Las propiedades constantes no pueden tener métodos de escritura ni señales de notificación.

FINAL: Indica que las clases derivadas no anularán esta propiedad. Esto se puede utilizar para optimizar el rendimiento en algunos casos, pero moc no lo aplica.

C++11 =predeterminado y =eliminar

En C ++ 11, cuando definimos una función miembro de una clase, si luego se modifica con "= eliminar", significa que la función se define como eliminada, lo que significa que la función miembro ya no se puede llamar, de lo contrario Algo saldrá mal.
Antes de C++ 11, cuando queríamos que una clase no fuera copiada, definimos el constructor como privado, pero en C++ 11 no hay necesidad de hacer esto. Sólo necesitamos agregar =delete después del constructor. modificarlo.

El nombre del objeto obtiene el nombre de la clase.

obj->metaObject()->className() == QLatin1String("Dialog");

Cómo agregar carpetas en Qt para clasificar los directorios del árbol de la izquierda

Insertar descripción de la imagen aquí

  1. Cree una nueva carpeta en la ruta del proyecto actual, por ejemplo, asígnele un nombresrc
  2. En la carpeta src recién creada, cree un nuevo documento de texto y asígnele un nombre src.pri(cambie el sufijo txt a pri)
  3. Cambie a Qt, agréguelo al .pro del proyecto actual include(src/src.pri)y presione Ctrl+S para guardarlo.
  4. Después de guardar (tarda unos segundos), se mostrará la carpeta que agregó.
  5. Haga clic derecho en la carpeta src que agregó para agregar un nuevo archivo y crear archivos .h y .cpp.

La diferencia entre setStatusTip, setToolTip y setWhatsThis

setStatusTip se usa para la punta de la barra de estado de MainWindow;
setToolTip se usa para la punta del control;
setWhatsThis se usa para la información de ayuda en el cuadro de diálogo.

¿Las clases personalizadas de Qt necesitan heredar QObject?

La clase QObject es la clase base para todos los objetos Qt.
Es mejor que las clases personalizadas hereden QObject, y también se debe escribir la macro Q_OBJECT.
Facilita el uso de señales y slots.

Errores comunes de compilación de Qt

  1. error: 'tr' no fue declarado en este ámbito...
    tr() es una función miembro de la clase QObject.
    Motivo: la clase personalizada no hereda QObject

La barra de herramientas de la ventana principal cambia el tamaño del icono

toolBar->setIconSize(QSize(18,18));

Eliminar las elipses contenidas en elementos en QComboBox

Al configurar el ancho máximo de QComboBox:

combox->setMaximumWidth(100);

Si el contenido del elemento es relativamente largo, aparecerán puntos suspensivos en el medio del elemento, lo que no se ve bonito:
Insertar descripción de la imagen aquí
la solución para cancelar los puntos suspensivos:

combox->view()->setTextElideMode(Qt::ElideNone);  //取消项中的省略号,但是会导致看不见后面的字体

Insertar descripción de la imagen aquí

enum TextElideMode {
    
    
        ElideLeft,    //省略号在最左边
        ElideRight,   //省略号在最右边
        ElideMiddle,  //省略号在最中间
        ElideNone     //无省略号
    };

Hay dos barras de herramientas, cómo mover una barra de herramientas hacia la derecha (alineada a la derecha)

Configure un widget en la barra de herramientas principal, coloque las dos barras de herramientas dentro del widget y use QHBoxLaout para el diseño. Una se coloca en el Qt::AlignLeft izquierdo, la otra se coloca en el Qt::AlignRight derecho y se coloca un resorte. entre los dos..
Establecer en la primera barra de herramientas:

	QWidget* widget = new QWidget(this);
    QComboBox* com1 = new QComboBox(this);
    QComboBox* com2 = new QComboBox(this);

    QToolBar* bar1 = new QToolBar(widget);
    bar1->addWidget(com1);
    QToolBar* bar2 = new QToolBar(widget);
    bar2->addWidget(com2);

    QHBoxLayout* lay = new QHBoxLayout;
    lay->addWidget(bar1, Qt::AlignLeft);
    lay->addStretch();
    lay->addWidget(bar2, Qt::AlignRight);
    widget->setLayout(lay);
    ui->mainToolBar->addWidget(widget);

Qwidget

El widget dibuja el color de fondo.

//CustomLabel继承与QLabel
void CustomLabel::setBackgroundColor(const QColor& color) {
    
    
    QPalette palette;
    palette.setColor(QPalette::Background, color);
    setAutoFillBackground(true);
    setPalette(palette);
}

widget establece borde

/**
 * @brief paintEvent: 绘制边框
 */
void ProjectTree::paintEvent(QPaintEvent* event) {
    
    
    Q_UNUSED(event)
    QPainter p(this);
    p.setPen(Qt::black);                          //设置画笔记颜色
    p.drawRect(0, 0, width() - 1, height() - 1);  //绘制边框
}

Haga clic con el mouse en otro lugar para ocultar el widget actual

setWindowFlags(Qt::Popup);

Colocar ventana debajo de la ventana actual

void QWidget::stackUnder(QWidget *w)

Coloque el widget debajo de w en la pila de widgets principal. Para hacer esto, el widget en sí y w deben ser hermanos (tanto el widget como w heredan de una clase principal).
Por ejemplo: quiero colocar una ventana debajo de la ventana emergente actual. La ventana actual hereda QDialog, por lo que la ventana que se colocará también debe heredar QDialog.

Cómo obtener la ventana de la clase padre.

QWidget* mainWindow = this->parentWidget()

Por ejemplo

Registro del tipo de datos personalizado Q_DECLARE_METATYPE()

La función QFontMetrics calcula el tamaño de los caracteres y cadenas de una fuente determinada.

  QFont font("times", 24);
  QFontMetrics fm(font);
  int pixelsWide = fm.width("What's the width of this text?");
  int pixelsHigh = fm.height();
QString elidedText(const QString &text, Qt::TextElideMode mode, int width, int flags = 0) const;

(Elide: significado de omisión)
Si el ancho del texto de la cadena es mayor que el ancho, se devuelve la versión omitida de la cadena (es decir, la cadena que contiene "..."). De lo contrario, se devuelve la cadena original.

enum TextElideMode {
    
    
        ElideLeft,    //省略号在左边
        ElideRight,   //省略号在右边
        ElideMiddle,  //省略号在中间
        ElideNone     //无省略号
    };

Macro

Q_ASSERT

Q_ASSERT es una macro que acepta un valor booleano. Cuando el valor booleano es verdadero, no hace nada. Cuando el valor booleano es falso, se detiene.

Q_ASSERT(index.isValid());

Errores de compilación comunes

error: error en la aserción estática: la ranura requiere más argumentos de los que proporciona la señal. [ #define Q_STATIC_ASSERT_X(Condición, Mensaje) static_assert(bool(Condición), Mensaje)]

Motivo: Generalmente causado por inconsistencia en los parámetros de señales y ranuras.

error: No hay regla para hacer que el destino sea 'xxx.png', necesario para 'debug/qrc_resource.cpp'. Detener.

Causa: Eliminando imágenes bajo recursos en el proyecto
Solución: Vuelva a ejecutar qmake.

error: [debug/qrc_resource.cpp] Error 1

Insertar descripción de la imagen aquí

Motivo: esta imagen se agregó al proyecto, pero no existe en el archivo (o se eliminó). No se puede encontrar en este momento, por lo que se informa un error. ¿Cómo encontrar esta imagen inexistente
?
Método: Haga clic en las imágenes una por una, al hacer clic en una imagen que no existe, se mostrará el siguiente error.
Insertar descripción de la imagen aquí

Solución: elimine esta imagen del proyecto y agréguela nuevamente

error: el campo tiene tipo incompleto

Motivo: Es solo una declaración directa y no incluye el archivo de inclusión
Solución: Incluya el archivo de inclusión.

error: saltar a la etiqueta del caso [-fpermissive] caso xxx: ^

Motivo: si hay varias líneas de código de definición después de la declaración del caso, especialmente definiciones de variables , es mejor usar {} para dar el alcance de la restricción, porque la computadora no puede reconocer el alcance.
Solución: agregue {} al código después de la declaración del caso

//Ejemplo de error:

switch (a)
{
    
    
    case 1:
        int a = 0;
        //stuff
        break;

    case 2:
        //stuff
        break;
}

//Demostración correcta:

switch (a)
{
    
    
    case 1:
        {
    
    
            int a = 0;
            //stuff
        }
        break;

    case 2:
        //stuff
        break;
}

error: pasar 'const ProjectTreeViewDelegate' como argumento 'este' descarta los calificadores [-fpermissive] drawTreeViewItem(painter, drawRect, modelData);^

Motivo: cuando una función es una función constante y otra función llamará a los parámetros de esta función, la otra función también debe configurarse como constante
Solución: la otra función también debe ser una función constante.

Ejemplo de error:

void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
void drawTreeViewItem(QPainter* painter, QRect drawRect, ProjectTreeModelData modelData);  //错误

Demostración correcta:

//drawTreeViewItem参数里面会调用paint的参数,paint为const函数,则drawTreeViewItem也应为const函数
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
void drawTreeViewItem(QPainter* painter, QRect drawRect, ProjectTreeModelData modelData) const;

Otra situación:
el valor de una variable miembro no se puede cambiar ni asignar en una función constante.

error: argumento predeterminado dado para el parámetro x de

Motivo: los parámetros predeterminados se pueden declarar en una declaración de función o en una definición de función, pero no se pueden declarar tanto en una declaración de función como en una definición de función.
Solución: simplemente elimine cualquier parámetro predeterminado en la definición o declaración.

Ejemplo de error:

//.h文件
void func(int a, int b = 0);
//.cpp文件
void func(int a, int b = 0);  //错误

Demostración correcta:

//.h文件
void func(int a, int b = 0);
//.cpp文件
void func(int a, int b);

error: error en la aserción estática: los argumentos de señal y ranura no son compatibles.

Motivo: Los parámetros de la señal no corresponden a los parámetros de la función de ranura
Solución: Los parámetros de la señal y los parámetros de la función de ranura se cambian para que sean consistentes.

Ejemplo de error:

//信号
sigData(int a);
//槽函数
slotGetData(float a);  //错误,参数不一致

Demostración correcta:

//信号
sigData(int a);
//槽函数
slotGetData(int a);

error: aplicación no válida de 'sizeof' al tipo incompleto 'XXX'('VariableData'): sizeOf = sizeof(T)

Motivo: Predeclarar una clase es solo una declaración y no se conoce el tamaño de la clase.
Solución: Utilice include para incluir el archivo de encabezado.

Ejemplo de error:

class B;  //只是声明
class A  {
    
    
	...
    QList<B> m_ list;  //无法知道类B的大小
};

Demostración correcta:

#include "B.h"

class A  {
    
    
	...
    QList<B> m_ list;
};

Error sobre en línea: uso no válido del tipo incompleto 'xxx'

Motivo: Inline se declara en el archivo de encabezado. Cuando se define en el archivo fuente, si otros archivos llaman a la función en línea, se producirá este error. Debido a que esta función no es visible para otras unidades de compilación, es decir, otros archivos cpp no ​​pueden vincularse a esta biblioteca de funciones.
Solución: la declaración y definición de la función en línea están escritas en el archivo de encabezado

  • Si la implementación de la función se coloca en un archivo de encabezado, entonces cada archivo cpp que contenga el archivo de encabezado obtendrá una definición de la función y el vinculador informará un error de redefinición de la función.
  • Si la implementación de la función se coloca en el archivo de encabezado y se marca en línea, entonces cada archivo cpp que contenga el archivo de encabezado obtendrá una definición de la función y el vinculador no informará un error.
  • Si la implementación de la función se coloca en el archivo cpp y no está marcada en línea, la función se puede vincular a otras unidades de compilación.
  • Si la implementación de la función se coloca en el archivo cpp y se marca en línea, entonces la función no es visible para otras unidades de compilación (similar al efecto estático), es decir, otros archivos cpp no ​​pueden vincularse a la biblioteca de funciones, que es lo que aparece. en el título... referencia indefinida a...

Error de error lambda de la función de ranura: pasar 'const VarBasicData' como argumento 'este' descarta los calificadores [-fpermissive][=](const VarBasicData& varinfo) { varData.basic = varinfo; });

Motivo: el parámetro es constante y se producirá un error durante la asignación.
Solución: agregue la palabra clave mutable

Ejemplo de error:

connect(SignalsMedium::getInstance(), &SignalsMedium::sigBasicVarInfo,
            [=](const VarBasicData& varinfo) {
    
     varData.basic = varinfo; });

Demostración correcta:

connect(SignalsMedium::getInstance(), &SignalsMedium::sigBasicVarInfo,
            [=](const VarBasicData& varinfo) mutable {
    
     varData.basic = varinfo; });

La función de actualización()

Se utiliza para actualizar la interfaz de usuario, activará el evento de redibujado y llamará a la función paintEvent .
En QWidget o sus subclases, puede activar el evento de redibujo llamando a la función de actualización para actualizar la interfaz de usuario.

Color Q

nombre del color de impresión

QString QColor::name() const
qDebug() << color.name();

color básico

QString arrayColor[5][8] = {
    
    
        {
    
    "#000000", "#A52A2A", "#004040", "#005500", "#00005E", "#00008B", "#4B0082", "#696969"},
        {
    
    "#8B0000", "#FF6820", "#8B8B00", "#009300", "#388E8E", "#0000FF", "#7B7BC0", "#808080"},
        {
    
    "#FF0000", "#FFAD5B", "#32CD32", "#3CB371", "#7FFFD4", "#7D9EC0", "#800080", "#A9A9A9"},
        {
    
    "#FFC0CB", "#FFD700", "#FFFF00", "#00FF00", "#40E0D0", "#C0FFFF", "#480048", "#C0C0C0"},
        {
    
    "#FFE4E1", "#D2B48C", "#FFFFE0", "#98FB98", "#AFEEEE", "#68838B", "#E6E6FA", "#FFFFFF"}};

    QString arrayToolTip[5][8] = {
    
    
        {
    
    "Black", "Brown", "Dark Olive Green", "Dark Green", "Dark Teal", "Dark Blue", "Indigo", "Dark Gray"},
        {
    
    "Dark Red", "Orange", "Dark Yellow", "Green", "Teal", "Blue", "Blue Gray", "Gray"},
        {
    
    "Red", "Light Orange", "Lime", "Sea Green", "Aqua", "Light Blue", "Violet", "Dim Gray"},
        {
    
    "Pink", "Gold", "Yellow", "Bright Green", "Turquoise", "SkyBlue", "Dark Magenta", "Light Gray"},
        {
    
    "Light Pink", "Tan", "Light Yellow", "Pale Green", "Pale Turquoise", "Pale Blue", "Lavender", "White"}};

evento: establece el estilo del marco cuando el mouse entra y sale

bool BasicColorItem::event(QEvent* event) {
    
    
    /*鼠标进入时的框架样式*/
    if (QEvent::Enter == event->type()) {
    
    
        setLineWidth(0);
        setMidLineWidth(0);
        setFrameShape(QFrame::WinPanel);
        setFrameShadow(QFrame::Raised);
    }

    /*鼠标离开时的框架样式*/
    if (QEvent::Leave == event->type()) {
    
    
        initItemFram();
    }

    return QLabel::event(event);
}

El papel de INCLUDEPATH en .pri

Si hay: INCLUDEPATH += $$PWD/treeview/
, directamente en otros niveles de archivos: #include "abc.h"

Si no hay: INCLUDEPATH += $$PWD/treeview/
, debe buscar nivel por nivel en otros niveles de archivos e incluir: #include "xxx/yyy/zzz/abc.h"

Configure solo el botón de cerrar en la esquina superior derecha

setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
setWindowModality(Qt::WindowModal);  //模态窗口

¿Puedo regresar directamente antes del descanso (tengo que hacer un descanso después del regreso en el cambio)?

El uso de return en el interruptor no solo saltará fuera del interruptor, sino que también finalizará directamente el ciclo.
Se sabe que cuando se ejecuta break, el interruptor saltará y las declaraciones posteriores ya no se ejecutarán; return tiene el mismo efecto.

En la idea, ya sea que escriba un descanso después del regreso o un regreso después del descanso, se informará un error directamente y no se podrá llegar a la declaración.

Bucle for multinivel, break solo saltará de un nivel del bucle

QTreeView

establecer la configuración de atributos

setHeaderHidden(true);                               //隐藏标题
setExpandsOnDoubleClick(false);                      //是否双击展开项
setRootIsDecorated(false);                           //是否显示展开和折叠顶级项的控件(v和>)
setEditTriggers(QAbstractItemView::NoEditTriggers);  //不可编辑
setIndentation(0);                                   //所有项的缩进为0
setAcceptDrops(true);                                //接受拖放事件
setAnimated(true);                                   //子项展开的动画

SetExpanded no expande el problema

Problema: cuando no hay nodos secundarios en el elemento actual, setExpanded no es válido. Primero debe agregarRow() y luego setExpanded().
setExpanded debe configurarse desde el nodo superior hacia abajo. Si se configura hacia arriba desde el nodo inferior, no será válido.

setExpanded no es válido de adentro hacia afuera (configure primero el nodo descendiente, luego configure el nodo principal), ejemplo:

QStandardItem* currentItem  = new QStandardItem;
m_model->appendRow(currentItem);
for(int i = 0; i < 3; ++i){
    
    
	QStandardItem* childItem  = new QStandardItem;
	for(int i = 0; i < 5; ++i){
    
    
		QStandardItem* grandsonItem  = new QStandardItem;
		childItem->appendRow(grandsonItem);
	}
	//此时想的是给childItem添加完子节点后,再去展开它,但是当前节点的父节点都不知道展开了没有,在这里展开子节点是豪无意义的
	//所以这里的childItem展开是无效的。在这之前必须先设置父节点的setExpanded
	setExpanded(childItem ->index(), true);  
	
	currentItem->appendRow(childItem );  
}
setExpanded(currentItem->index(), true);  //currentItem展开

El código anterior provocará: childItem no se expandirá

Corrección: setExpanded debe configurarse de afuera hacia adentro ( de padre a hijo, luego a nieto, setExpanded )

//每次appendRow之后就setExpanded
QStandardItem* currentItem  = new QStandardItem;
m_model->appendRow(currentItem);
setExpanded(currentItem->index(), true);  //currentItem展开
for(int i = 0; i < 3; ++i){
    
    
	QStandardItem* childItem  = new QStandardItem;
	currentItem->appendRow(childItem );  
	setExpanded(childItem ->index(), true);  
	for(int i = 0; i < 5; ++i){
    
    
		QStandardItem* grandsonItem  = new QStandardItem;
		childItem->appendRow(grandsonItem);
	}			
}

Cómo asignar valores a iteradores: use *blockIter

for (QList<BlockData>::iterator blockIter = osciModelData.oscilloscope.blockDList.begin();
     blockIter != osciModelData.oscilloscope.blockDList.end(); ++blockIter) {
    
    
    if (blockModelData.block.uid == blockIter->uid) {
    
      //找到是哪个Block
        *blockIter = blockModelData.block;
    }
}

Definición de enumeración

Los elementos de enumeración de diferentes tipos de enumeración no pueden tener el mismo nombre

Uso de findChild

Devuelve un elemento secundario de QPushButton llamado "botón1" en el widget principal, aunque el botón no sea un elemento secundario directo del elemento principal:

QPushButton *button = parentWidget->findChild<QPushButton *>("button1");

Devuelve un hijo QListWidget en parentWidget:

QListWidget *list = parentWidget->findChild<QListWidget *>();

Devuelve un elemento secundario de QPushButton llamado "botón1" en parentWidget (su padre directo):

QPushButton *button = parentWidget->findChild<QPushButton *>("button1", Qt::FindDirectChildrenOnly);

Devuelve un hijo QListWidget dentro de parentWidget (su padre directo):

QListWidget *list = parentWidget->findChild<QListWidget *>(QString(), Qt::FindDirectChildrenOnly);

conectar

Cómo escribir conectar

expresión lambda de conectar

connect(pushButton, &QPushButton::clicked, [=](){
    
    ...});
// [=]代表把外部所有局部变量、类中所有成员以值的传递方式;如果当前connect处于某个函数中,则表示当前函数下的所有变量、类中所有成员以值的传递方式
// [this]代表把类中所有成员以值的传递方式  
// [&]代表把外部所有局部变量、类中所有成员以引用的传递方式;如果当前connect处于某个函数中,则表示当前函数下的所有变量、类中所有成员以引用的传递方式
// ()传递过来的参数

connect(m_var, &QPushButton::sigSetVar, [=](const VarData& data) mutable {
    
    ...});
//如果参数为const类型,并且后面使用到该参数,比如赋值之类的,需要写mutable,去掉const属性

Captura de valor [=] y captura de referencia [&] en lambda

Captura por valor[=]

	ProjectTreeModelData varModelData = varStandardItem->data(Qt::UserRole + 1).value<ProjectTreeModelData>();
	connect(colorWidget, &ColorSelectedDialog::sigBasicColor, [=](const QColor& color) mutable {
    
    
		//此时获得是varModelData的副本
		varModelData.variable.variableData.lineColor = color.name();   //若color是蓝色
    	colorWidget->close();
	});
	//因为上面的赋值是赋给varModelData的副本,这里的setData中varModelData中lineColor还是原来的颜色
	varStandardItem->setData(QVariant::fromValue(varModelData), Qt::UserRole + 1);
	//此时获得的varModelData中lineColor还是原来的颜色,并没有改变为蓝色
	varModelData = varStandardItem->data(Qt::UserRole + 1).value<ProjectTreeModelData>();  

Captura por referencia [&]

	ProjectTreeModelData varModelData = varStandardItem->data(Qt::UserRole + 1).value<ProjectTreeModelData>();
	connect(colorWidget, &ColorSelectedDialog::sigBasicColor, [&](const QColor& color) mutable {
    
    
		//此时获得是varModelData本身,而非副本
		varModelData.variable.variableData.lineColor = color.name();   //若color是蓝色
    	colorWidget->close();
	});
	//因为上面的赋值是赋给varModelData结构本身,这里的setData中varModelData中lineColor已成为蓝色
	varStandardItem->setData(QVariant::fromValue(varModelData), Qt::UserRole + 1);
	//此时获得的varModelData中lineColor变为蓝色
	varModelData = varStandardItem->data(Qt::UserRole + 1).value<ProjectTreeModelData>();  

Antes de enviar una señal, primero se debe establecer una conexión.

Por ejemplo, al enviar datos a otra interfaz, la conexión debe establecerse primero en esa interfaz; de lo contrario, el lado de ejecución de la señal no recibirá los datos.

Para otro ejemplo, debes escribir connect antes de exec() en una interfaz, porque exec() bloqueará el siguiente código.

Generalmente, está escrito en el constructor y comienza a monitorear durante la inicialización. Las situaciones específicas se abordarán caso por caso.

Connect está anidado en connect, preste atención a las conexiones repetidas.

connect(addVarAct, &QAction::triggered, [=]() {
    
    
        connect(SignalsMedium::getInstance(), &SignalsMedium::sigBasicVarInfo,
                [=](const VarBasicData& varinfo) mutable {
    
     addVariable(blockStandardItem, varinfo); });

Problema: Connect está anidado dentro de connect, lo que hace que el connect interno se conecte repetidamente.
Solución: use desconectar para desconectar

connect(addVarAct, &QAction::triggered, [=]() {
    
    
        connect(SignalsMedium::getInstance(), &SignalsMedium::sigBasicVarInfo,
                [=](const VarBasicData& varinfo) mutable {
    
     addVariable(blockStandardItem, varinfo); });
		...
        /** 必须断开连接,否则会每点一次就会多连接一次,造成重复连接 **/
        disconnect(SignalsMedium::getInstance(), &SignalsMedium::sigBasicVarInfo, 0, 0);

parámetros de conexión

Una señal se puede conectar a múltiples ranuras y señales. Si una señal está conectada a varias ranuras, cuando se emita la señal, las ranuras se activarán en el orden en que fueron conectadas.
enumeración Qt::Tipo de conexión

Constante Valor Descripción
Qt::Autoconexión 0 (Predeterminado) Utilice Qt::DirectConnection si el receptor está en el hilo que emitió la señal. De lo contrario, utilice Qt::QueuedConnection. Determina el tipo de conexión al señalizar.
Qt::Conexión Directa 1 Esta ranura se llama inmediatamente cuando se emite la señal. Las ranuras se ejecutan en el mismo hilo.
Qt::Conexión en cola 2 Esta ranura se llama cuando el control regresa al bucle de eventos del hilo receptor. La ranura se ejecuta en el hilo del receptor.
Qt::Bloqueo de conexión en cola 3 Igual que Qt::QueuedConnection, excepto que el hilo de señal se bloquea hasta que regresa la ranura. Esta conexión no se puede utilizar si el remitente y el receptor están en el mismo hilo; de lo contrario, la aplicación se bloqueará.
Qt::Conexión única 0x80 Este es un indicador que se puede usar en combinación con cualquiera de los tipos de conexión anteriores usando OR bit a bit. Si la señal actual y la ranura se han conectado, ya no estarán conectadas para evitar conexiones repetidas.

Cómo evitar conexiones repetidas en connect

Especialmente si la conexión está anidada dentro de la conexión, es particularmente fácil causar conexiones repetidas dentro de la conexión.
Solución:
(1) desconectar; (en algunos casos, si cada conexión interna maneja cosas diferentes, es mejor usar desconectar)
(2 ) ) Escriba connect en la estructura; (No todas las conexiones se pueden escribir en la estructura. Si una interfaz no es nueva en la estructura, la conexión vinculada a la interfaz no será válida) (3) blockSignals (bloquee todas las señales de
la se envían los controles);
(4) Qt::UniqueConnection; (En algunos casos, si cada conexión interna maneja lo mismo, se usa Qt::UniqueConnection)

Sobrecarga de la función de conexión de ranura de señal y problemas de inconsistencia de parámetros

El método de escritura QT5 provoca errores de compilación

connect(m_thread, &QThread::started, m_timer, &QTimer::start);  //线程开始,定时器开始

Motivo: start() es una función sobrecargada. Dado que QT5 no indica parámetros de esta manera , el compilador no puede determinar qué función está conectada e informa un error. Solo
Insertar descripción de la imagen aquí
se puede utilizar el método de escritura QT4.

connect(m_thread, SIGNAL(started()), m_timer, SLOT(start()));  //线程开始,定时器开始

Cuando se hace clic con el mouse del cuadro de diálogo fuera de la ventana, la ventana se cerrará.

Diálogo para modales

  • Establezca el atributo de la ventana en Qt::Popup para cerrar automáticamente la ventana haciendo clic fuera de la ventana.
setWindowFlags(Qt::Popup);

Los dos métodos siguientes no son aplicables a los cuadros de diálogo modales, sino solo a los cuadros de diálogo y widgets no modales.

  • Anule el evento de clic del mouse (mousePressEvent()). Si la posición del mouse no está dentro del área de la ventana, cierre la ventana.
  • Anule el evento de pérdida de foco (focusOutEvent()). Si la ventana pierde el foco, ciérrela

Índice de modelo Q

Devuelve el índice hermano de la fila y columna del índice actual.

QModelIndex::sibling(int row, int column)

Insertar descripción de la imagen aquí
Los índices entre hermanos se pueden obtener entre sí, solo necesitas conocer las filas y columnas de los hermanos.

QModelIndex index0 = index1.sibling(index.row(), 0);
QModelIndex index3 = index1.sibling(index.row(), 3;

Insertar descripción de la imagen aquí```cpp

QModelIndex index0 = index1.sibling(0, index.column());
QModelIndex index3 = index1.sibling(3, index.column());

Eliminar nodos secundarios del árbol

Ejemplo de error:

// 每移除一个子节点,其m_projectNameItem->rowCount()都会少1
//而移除的是m_projectNameItem->child(i),导致某些子节点没有删除
if (m_projectNameItem->hasChildren()) {
    
    
	for (int i = 0; i < m_projectNameItem->rowCount(); ++i) {
    
    
		removeStandardItem(m_projectNameItem->child(i), m_projectNameItem);
	}
}
m_model->removeRow(m_projectNameItem->row());

Ejemplo correcto:

//先确定有多少个子节点
//每次都删第一个,才能保证删完
if (m_projectNameItem->hasChildren()) {
    
    
	int count = m_projectNameItem->rowCount();
	for (int i = 0; i < count; ++i) {
    
    
		removeStandardItem(m_projectNameItem->child(0), m_projectNameItem);
	}
}
m_model->removeRow(m_projectNameItem->row());

Eliminar recursivamente nodos secundarios de un árbol

removeStandardItem(QStandardItem* standardItem, QStandardItem* parentStandardItem) {
    
    
    int count = standardItem->rowCount();
    if (0 == count) {
    
    
        parentStandardItem->removeRow(standardItem->row());
        return;
    }

    for (int i = 0; i < count; ++i) {
    
    
        QStandardItem* childStandardItem = standardItem->child(0);
        removeStandardItem(childStandardItem, standardItem);
    }

    parentStandardItem->removeRow(standardItem->row());
}

QLine

setText activará la señal textChanged de QLineEdit

Establecer estado no editable:

setReadOnly(true); //只读

Conversión entre coordenadas actuales y coordenadas globales

QRect toolRect = geometry();
QPoint point(geometry().x + 100, geometry().y());
QPoint globalPoint = mapToGlobal(point);

Determinar si el foco actual está en un control.

hasFocus();

Qt gana y pierde eventos de enfoque

Anular la función focusInEvent()de suma del controlfocusOutEvent()

void focusInEvent(QFocusEvent *event) override;
void focusOutEvent(QFocusEvent *event) override;

Comparación sobre la lista

//错误示范
if (RTTVarList.at(i).basic == varModelData.variable.variableData.basic) {
    
    ...}
//正确示范
//list的at()是const类型的,放在==的右边
if (varModelData.variable.variableData.basic == RTTVarList.at(i).basic) {
    
    ...}

Arrastrar Cómo mostrar el signo de arrastre deshabilitado

Implementado en dragMoveEvent (evento QDragMoveEvent*), aparecerá un letrero deshabilitado al moverse a ciertas posiciones

//当鼠标移动到rect里面时,接受该事件,否则忽略该事件,就会出现禁用标志
void dragMoveEvent(QDragMoveEvent* event){
    
    
	QRect rect(0,0,100,30);
	if(ret.contains(event.pos())){
    
    
		event->accept();
	}else{
    
    
		event->ignore();	
	}
}

Insertar descripción de la imagen aquí

Cuadro de diálogo QFile

enumeración QFileDialog::AcceptMode

Estilo de apertura del cuadro de diálogo de archivo

  • AceptarAbrir: abre el archivo
    Insertar descripción de la imagen aquí
  • AceptarGuardar: Guarda el archivo
    Insertar descripción de la imagen aquí

enumeración QFileDialog::DialogLabel

Para etiquetas en cuadros de diálogo, puede usar setLabelText() para configurar el texto en la etiqueta.
Buscar en
Nombre de archivo
Tipo de archivo
Aceptar
Rechazar
Insertar descripción de la imagen aquí

El problema de que setFocus no surte efecto

No puedes configurar Focus cuando tu widget aún no está visible, eso no funcionará.
La forma de resolver este problema es poner la operación setFocus() en **showEvent()** de nuestro componente.
Generalmente nos gusta poner setFocus al final del constructor, pero esto muchas veces no tiene ningún efecto, este es el problema.

void DisplayWidget::showEvent(QShowEvent* event) {
    
    
    Q_UNUSED(event);
    m_osciNameLine->setFocus();
}

Guess you like

Origin blog.csdn.net/WL0616/article/details/130296740