Qt的日常编程过程中遇见的问题和注意
- Qt的日常编程过程中遇见的问题
- 1.QString和String的转化的格式问题,中文转化过程中会出现问题。
- 2.使用qcustomplot的时候出现错误:LINK2019:无法解析的外部符号
- 3.Qt报错常量有换行符
- 4.Qt使用MSVC编译器输出中文的问题
- 5.Qt中怎么进行输入参数进行调试?
- 6.错误:LINK2005:已经在main.obj中定义
- 7.错误:pure virtual method called
- 8.使用qt官方的simplebrowser报错:Render process exited with code: 159 Do you want to reload the page ?
- 9. :-1: error: /opt/Qt5.14.2/5.14.2/gcc_64/lib/libQt5WebEngineCore.so: .dynsym local symbol at index 3 (>= sh_info of 3)
- Qt中一些使用:
Qt的日常编程过程中遇见的问题
1.QString和String的转化的格式问题,中文转化过程中会出现问题。
解决方案:
QString str2qstr(const string str)
{
return QString::fromLocal8Bit(str.data());
}
string qstr2str(const QString qstr)
{
QByteArray cdata = qstr.toLocal8Bit();
return string(cdata);
}
2.使用qcustomplot的时候出现错误:LINK2019:无法解析的外部符号
错误:
解决方案:
在pro文件中增加 printsupport
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
greaterThan(QT_MAJOR_VERSION, 4): CONFIG += c++11
lessThan(QT_MAJOR_VERSION, 5): QMAKE_CXXFLAGS += -std=c++11
TARGET = plot-examples
TEMPLATE = app
3.Qt报错常量有换行符
错误:
解决方案:
选择《工具》=>《选项》
修改成如图片一样的设置。
最后编译一些,看会不会出现乱码的现象。如果会,就在字符前增加C++的语法u8""
QString str=u8"文件是:";
4.Qt使用MSVC编译器输出中文的问题
错误:在Qt Creator中使用MSVC编译器编译项目时,若处理不当容易出现中文字符串乱码问题。
分析原因:这是因为Qt Creator保存的文件使用的是UTF-8编码(是任何平台、任何语言都可以使用的跨平台的字符集),MSVC编译器虽然可以正常编译带BOM的UTF-8编码的源文件,但是生成的可执行文件的编码是Windows本地字符集,比如GB2312。也就是在可执行文件中,字符串是以GB2312编码的,而可执行程序执行到这条语句时,对这个字符串却是以UTF-8解码的,这样就会出现乱码。
解决方案:
第一种:使用QStringLiteral()宏封装字符串,另一种方法是强制MSVC编译器生成的可执行文件使用UTF-8编码。
QString str=QStringLiteral("当前位置:")+QString::asprintf("%d %%",arg1);
程序中需要使用QStringLiteral()宏对每个中文字符串进行封装,并且不能再使用tr()函数用于翻译字符串。
第二种:
强制MSVC编译器采用UTF-8编码生成可执行文件,需要在每个使用到中文字符串的头文件和源程序文件的前部加入如下的语句:
#if _MSC_VER >= 1600 //MSVC2015>1899, MSVC_VER=14.0
#pragma execution_character_set("utf-8")
#endif
MSVC2010以后的编译器可以使用此方案,这是强制编译后的执行文件采用UTF-8编码。这样,即使不再使用QStringLiteral()宏,程序运行时也不会再出现汉字乱码的问题了。而且,也可以采用tr()函数用于翻译字符串。
5.Qt中怎么进行输入参数进行调试?
问题:就是如果我的程序是可以输入参数进行运行的。那么要怎么输入参数进行程序的运行?
解决方案:进入如下界面
在command line arguments(命令行参数)输入自己的参数就行,空格分开。
下面的run in terminal 是控制控制台窗口的选项。
6.错误:LINK2005:已经在main.obj中定义
错误:
解决方案:是因为我们在头文件中实现了一个全局函数。我们只有在头文件中声明,在cpp文件中是实现我们的函数就可以了。
7.错误:pure virtual method called
引起这个错误的问题很多:
常见的是:
1.当一个对象正在被析构时,它的虚函数被调用。这可能发生在析构函数中,或者在对象被删除后。例如,如果你在一个类的析构函数中调用了它的虚函数,那么当该类的实例被删除时,可能会出现“pure virtual method called”错误。
2.当一个抽象基类的实例被错误地创建时。这可能发生在使用new操作符创建抽象基类的实例时。例如,如果你试图使用new操作符创建一个包含纯虚函数的类的实例,那么可能会出现“pure virtual method called”错误。
要解决这个问题,你需要检查你的代码,确保没有调用纯虚函数。如果你在析构函数中调用了虚函数,你应该将其移动到析构函数之外。如果你错误地创建了抽象基类的实例,你应该改为创建其派生类的实例。
我检查了这些还是错误,原来我是因为自己代码设置布局的时候,都是在栈空间
错误代码:
class PlcInfoWidget:public QDialog{
Q_OBJECT
public:
explicit PlcInfoWidget(QWidget *parent = nullptr):QDialog (parent){
//
setWindowTitle(tr("增加设备"));
m_leIp.setInputMask("000.000.000.000");
m_leIp.setValidator(new IpValidator(this));
okBtn.setText(tr("确定"));
noBtn.setText(tr("取消"));
connect(&okBtn,&QPushButton::clicked,this,&PlcInfoWidget::accept);
connect(&noBtn,&QPushButton::clicked,this,&PlcInfoWidget::reject);
m_laIp.setText(tr("IP:"));
m_laPortC.setText(tr("C口轴数:"));
m_laPortD.setText(tr("D口轴数:"));
v1.setSpacing(7);
h1.setSpacing(10);
h2.setSpacing(10);
h3.setSpacing(10);
h4.setSpacing(30);
h4.addWidget(&okBtn);
h4.addWidget(&noBtn);
h1.addWidget(&m_laIp);
h1.addWidget(&m_leIp);
h2.addWidget(&m_laPortC);
h2.addWidget(&m_sbC);
h3.addWidget(&m_laPortD);
h3.addWidget(&m_sbD);
v1.addLayout(&h1);
v1.addLayout(&h2);
v1.addLayout(&h3);
v1.addLayout(&h4);
setLayout(&v1);
}
~PlcInfoWidget(){
qDebug()<<"析构了plcinfo";
};
private:
QPushButton okBtn;
QPushButton noBtn;
QLabel m_laPlc;
QLabel m_laIp;
QLabel m_portLabel;
QLabel m_laPortC;
QLabel m_laPortD;
QLineEdit m_leIp;
QSpinBox m_sbC;
QSpinBox m_sbD;
QHBoxLayout h1;
QHBoxLayout h2;
QHBoxLayout h3;
QHBoxLayout h4;
QVBoxLayout v1;
};
错误原因:
在PlcInfoWidget类中直接创建了多个布局对象(QHBoxLayout和QVBoxLayout)。在Qt中,当一个布局对象被设置为另一个布局或窗口部件的子布局时,它的内存管理将由其父布局或窗口部件负责。这意味着当父布局或窗口部件被删除时,子布局也会被自动删除。
创建了多个布局对象(h1、h2、h3、h4和v1),并将它们设置为PlcInfoWidget的子布局。这意味着当PlcInfoWidget被删除时,这些布局对象也会被自动删除。但是,由于这些布局对象是直接创建的,而不是通过new操作符动态分配的,因此当它们被自动删除时,可能会导致程序崩溃。
解决方案:
所以只要是new 出来布局就好了。
8.使用qt官方的simplebrowser报错:Render process exited with code: 159 Do you want to reload the page ?
错误原因:
别人分析错误原因是这个,这个我看不懂。
在这里,主要是关闭了两项安全功能:
- –disable-web-security:
这个参数用于禁用浏览器的一些网络安全策略。主要的影响包括:
(1) 跨源请求限制: 正常情况下,浏览器遵循同源政策(Same-Origin Policy),限制来自不同源的文档或脚本互相交互。使用 --disable-web-security 参数会禁用这种限制,允许所有跨源请求。
(2) 文件访问限制: 在没有这个参数的情况下,从本地文件系统加载的页面不能访问其他文件或目录。禁用Web安全性后,页面可以自由读取本地文件系统上的任何文件。 - –disable-seccomp-filter-sandbox
此参数用于禁用浏览器的 seccomp 沙盒。Seccomp(安全计算模式)是一个Linux内核特性,可以用来限制应用程序的系统调用:
(1) 系统调用限制: Seccomp沙盒能限制进程可以调用的系统调用,这是一种减少潜在安全风险的手段。启用 seccomp 可以防止恶意软件或被攻击的进程执行危险的系统调用。
(2) 提高安全性: 通过减少可用的系统调用,seccomp增加了浏览器进程的安全性,限制了潜在攻击者的操作空间。
笔者这里,在将第二项功能关闭后,问题即解决!第一项的关闭对笔者似乎没有作用,上述案例供大家参考。
解决方案:
这个解决方案,还解决了一个问题
QWebEngineView *view = new QWebEngineView();
view->load(QUrl("https://www.baidu.com/"));
view->show();
显示没有报错,但是就是页面都加载不出来。
int main(int argc, char **argv)
{
QCoreApplication::setOrganizationName("QtExamples");
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QtWebEngine::initialize();
// ---------------------------添加内容,自此开始------------------------
char ARG_DISABLE_WEB_SECURITY[] = "--disable-web-security";
char ARG_DISABLE_SECCOMP_SECURITY[] = "--disable-seccomp-filter-sandbox";
int newArgc = argc+1+1+1;// ARG_DISABLE_WEB_SECURITY + ARG_DISABLE_SECCOMP_SECURITY + nullptr
char** newArgv = new char*[newArgc];
for(int i=0; i<argc; i++) {
newArgv[i] = argv[i];
}
newArgv[argc] = ARG_DISABLE_WEB_SECURITY;
newArgv[argc+1] = ARG_DISABLE_SECCOMP_SECURITY;
newArgv[argc+2] = nullptr;
// Application app(argc, argv);
Application app(newArgc, newArgv);
// ---------------------------添加内容,自此结束------------------------
QQmlApplicationEngine appEngine;
Utils utils;
appEngine.rootContext()->setContextProperty("utils", &utils);
appEngine.load(QUrl("qrc:/ApplicationRoot.qml"));
if (!appEngine.rootObjects().isEmpty())
QMetaObject::invokeMethod(appEngine.rootObjects().first(), "load", Q_ARG(QVariant, startupUrl()));
else
qFatal("Failed to load sources");
return app.exec();
}
9. 👎 error: /opt/Qt5.14.2/5.14.2/gcc_64/lib/libQt5WebEngineCore.so: .dynsym local symbol at index 3 (>= sh_info of 3)
使用QWebEngineView 的时候出现了构建错误信息,虽然可以跳过编译错误信息,但是就会导致显示的界面是空白的。
QWebEngineView *view = new QWebEngineView();
view->load(QUrl("https://www.baidu.com/"));
view->show();
错误原因:
不明,
解决方案:
1.
sudo ln -sf /usr/bin/x86_64-linux-gnu-ld.gold /usr/bin/ld
CONFIG += use_gold_linker
LIBS += -ldl
sudo apt-get install lld
并将"CONFIG +=use_lld_linker"添加到 .pro 文件中
Qt中一些使用:
1.Qt的验证器的使用
ui->edit_fast_temp->setValidator(new QDoubleValidator(0,5.0,2,this));
ui->edit_hight_temp->setValidator(new QIntValidator(65,100,this));
2.使用qt的控制台,来调试信息
#pragma comment( linker, "/subsystem:\"console\" /entry:\"mainCRTStartup\"" ) // 设置连接器选项
//
const unsigned short WHITE_TRANS = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
const unsigned short GRAY_TRANS = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
const unsigned short GREEN_TRANS = FOREGROUND_GREEN ;
const unsigned short RED_TRANS = FOREGROUND_RED;
//
void setConsoleColour(unsigned short color)
{
static const HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
fflush(stdout);
SetConsoleTextAttribute(console, color);
}
//自定义消息
void message_output(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QDateTime time = QDateTime::currentDateTime();
QString time_str = time.toString("hh:mm:ss");
QByteArray local_msg = msg.toLocal8Bit();
QString lv;
int color = GRAY_TRANS;
switch (type) {
case QtDebugMsg:
lv = "D";
color = GRAY_TRANS;
break;
case QtInfoMsg:
lv = "I";
color = GREEN_TRANS;
break;
case QtWarningMsg:
lv = "W";
color = RED_TRANS;
break;
case QtCriticalMsg:
lv = "C";
break;
case QtFatalMsg:
lv = "F";
break;
}
setConsoleColour(color);
fprintf(stdout, "%s [%s]: %s\n", time_str.toStdString().c_str(), lv.toStdString().c_str(), local_msg.toStdString().c_str());
}
int main(int argc, char *argv[])
{
//使用自定义的消息进行输出,如果不使用这句话,会使用的是默认的qDebug(),qWrang().等默认的格式进行输出
qInstallMessageHandler(message_output);
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
只要这样配置好之后,就可以使用qt的调试的Q包含用于警告和调试文本的全局宏:
qDebug()调试消息
qInfo()信息消息
qWarning()警告消息和可恢复的错误
qCritical()关键错误和系统错误
qFatal()致命错误
来输出自己想要的格式的信息。
3.Qt的验证器的高级使用,自己自定义
功能:我们在输入ip的时候就想校验别人输入的数据是否符合,不符合就直接无效
代码实现:
#include <QValidator>
class IpValidator : public QValidator
{
public:
explicit IpValidator(QObject *parent = nullptr);
State validate(QString &input, int &pos) const override;
};
IpValidator::IpValidator(QObject *parent) :
QValidator(parent)
{
}
QValidator::State IpValidator::validate(QString &input, int &pos) const
{
Q_UNUSED(pos)
// 将输入分割为四个部分
QStringList parts = input.split(".");
// 如果输入包含超过四个部分,则返回Invalid
if (parts.size() > 4) {
return Invalid;
}
// 验证每个部分是否在0到255之间
for (const QString &part : parts) {
bool ok;
QString str = part.trimmed();//去掉IP前面后面的空格
int value = str.toInt(&ok);
//if (!ok || value < 0 || value > 255)
if(value < 0 || value > 255)//判断值是否在0到255之间
{
return Invalid;
}
}
// 如果输入包含四个部分,则返回Acceptable,否则返回Intermediate
return parts.size() == 4 ? Acceptable : Intermediate;
}