Qt 进程间通信

2023-11-01

Qt进程间通信的方法:

  1. TCP/IP
  2. Local Server/Socket
  3. 共享内存
  4. D-Bus (Unix库)
  5. QProcess
  6. 会话管理

TCP/IP :

使用套接字的方式,进行通信(之前介绍了,这里就不介绍了)。

Local Server/Socket 

跨平台Qt网络模块提供的类使本地网络编程变得可移植且简单。它提供了QLocalServer和QLocalSocket类,允许在本地设置中进行类似网络的通信。它们的 TCP 对应项可以用作直接替代品,以使跨网络通信工作。(使用方法和TCP相似) 

QLocalServer :

使用方法:

  1. listen()监听指定密钥上的传入连接
  2. 有客户端连接时,会发出newConnection()信号
  3. 使用nextPengingConnection()获取连接的QLocalSocket
  4. close()关闭监听

listen(QString)

监听
close() 关闭监听
errorString() 报告的当前错误的人类可读消息
fullServerName() 返回服务器正在侦听的完整路径
isListrening() 服务器正在侦听传入连接,true,否则为false
maxPendingConnection() 返回挂起的接受连接的最大数目。默认值为 30
nextPengingConnection() 将一个挂起的连接作为连接的 QLocalServer 对象返回
serverName() 则返回服务器名称
socketOption() 返回在套接字上设置的套接字选项
waitForNewConnection(int) 堵塞多少毫秒或直到传入连接可用

QLocalSocket

在Windows上是一个命名管道,在Unix上是一个本地套接字。

QLocalSocket 设计用于事件循环,但也可以在没有事件循环的情况下使用它。在这种情况下,您必须使用 waitForConnected()、waitForReadyRead()、waitForBytesWrite() 和 waitForDisconnected(),它们会阻止操作完成或超时到期。

使用方法:

  1. 使用connectToServer()与服务器简建立连接。
  2. 可以使用readData()读取数据,writeData()写入数据
  3. abort()断开连接
  4. close(),或disconnectFromServer()关闭套接字
connectToServer() 连接服务器
bytesAvailable() 获取数据大小
error() 返回上次发生的错误类型
flush() 此函数尽可能多地从内部写入缓冲区写入套接字,而不会阻塞。如果写入了任何数据返回true
fullServerName() 返回套接字连接到的服务器路径
isVaild() 判断套接字是否可用
readData() 读取数据
writeData() 写入数据
setReadBufferSize() 设置内部缓冲区大小
waitForConnected() 等待连接
waitForReadyRead() 等待读取
waitForBytesWrite() 等待写入
waitForDisconnected() 等待断开

 LoaclServer的搭建:

pro文件中添加:

QT  +network

在ui界面中添加:

QTextEdit 、QPushButton 和QLineEdit

.h文件:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QLocalServer>
#include<QLocalSocket>
#include<QMessageBox>
#include<QDataStream>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
    QLocalServer *localserver;//服务端
    QLocalSocket*localsocket=nullptr;//套接字

};
#endif // WIDGET_H

.cpp文件:

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("服务器端");
    localserver=new QLocalServer(this);
    localserver->listen("Good People");//Good People作为连接字符
    connect(localserver,&QLocalServer::newConnection,[=]()
    {
        localsocket=localserver->nextPendingConnection();//获取连接的套接字
        connect(localsocket,&QLocalSocket::readyRead,[=]()//如果有可读数据的话
        {
            QByteArray block;
            block=localsocket->readAll();
            QString S=block.data();
            ui->textEdit->append(QString("客户端:%1").arg(S));
        });

    });
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()//发送数据
{
    if(ui->lineEdit->text().isEmpty())
    {
        QMessageBox::information(this,"提示信息","请输入内容",QMessageBox::Ok);
        return;
    }
    ui->textEdit->setText(QString("服务器端:%1").arg(ui->lineEdit->text()));//设置内容
    if(localsocket->isValid())
    {
        QString S=ui->lineEdit->text();
        localsocket->write(S.toUtf8());//发送消息
    }

}

LocalSocket客户端的搭建:

pro文件中添加:

QT +=network

ui界面中添加:

.h文件:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QLocalSocket>
#include<QMessageBox>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

private:
    Ui::Widget *ui;
    QLocalSocket * localsocket;//套接字
};
#endif // WIDGET_H

.cpp文件:

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    localsocket=new QLocalSocket(this);
    setWindowTitle("客户端");
    connect(localsocket,&QLocalSocket::readyRead,[=]()
    {
        QByteArray block;
        block=localsocket->readAll();//读取信息
        ui->textEdit->append(QString("服务器:%1").arg(block.data()));//聊天框添加信息
    });

}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()//连接
{
    localsocket->abort();//先断开
    localsocket->connectToServer("Good People");//连接
}

void Widget::on_pushButton_2_clicked()//发送
{
    if(ui->lineEdit->text().isEmpty())
    {
        QMessageBox::information(this,"提示信息","请输入内容。",QMessageBox::Ok);
        return;
    }
    if(localsocket->isValid())
    {
        localsocket->write(ui->lineEdit->text().toUtf8());
        ui->textEdit->append(QString("客户端:%1").arg(ui->lineEdit->text()));
    }


}

运行效果:

 共享内存:

QSharedMemory

QSharedMemory 提供通过多个线程和进程对共享内存段的访问。它还为单个线程或进程提供了一种锁定内存以进行独占访问的方法。

使用此类时,请注意以下平台差异:

  • Windows:QSharedMemory 不“拥有”共享内存段。当将 QSharedMemory 实例附加到特定共享内存段的所有线程或进程都销毁其 QSharedMemory 实例或退出时,Windows 内核会自动释放共享内存段。
  • Unix:QSharedMemory“拥有”共享内存段。当将 QSharedMemory 实例附加到特定共享内存段的最后一个线程或进程通过销毁其 QSharedMemory 实例与该段分离时,Unix 内核将释放共享内存段。但是,如果在未运行 QSharedMemory 析构函数的情况下最后一个线程或进程崩溃,则共享内存段将在崩溃中幸存下来。
  • HP-UX:每个进程只允许一个附加到共享内存段。这意味着 QSharedMemory 不应在 HP-UX 中同一进程中的多个线程中使用。

注意:由于是共享内存,所以使用共享内存之前使用lock()锁定共享内存,使用完后需要解锁。当 QSharedMemory 的最后一个实例从共享内存段分离时,QSharedMemory 会自动销毁该段,并且不会保留对该段的引用。

常用函数:

setKey(QString) 设置此共享内存对象的平台独立
setNativeKey() 设置此共享内存对象的特定于平台的本机密钥。如果 key 与当前本机键相同,则函数返回而不执行任何操作。
lock() 对共享内存上锁
unlock() 对共享内存解锁
size() 返回附加的共享内存段的大小。如果未连接共享内存段,则返回 0。
isAttached() 如果此进程连接到共享内存段返回true
errorString() 错误信息
detach() 将进程与共享内存段分离。如果这是附加到共享内存段的最后一个进程,则系统将释放共享内存段,即内容被销毁。
data() 返回指向共享内存段内容的指针(如果已连接)
create() 使用传递给构造函数的键创建大小为字节共享内存段
constData() 返回指向共享内存段内容的 const 指针(如果已连接)
attach() 尝试将进程附加到由传递给构造函数的键或对 setKey() 或 setNativeKey() 的调用标识的共享内存段。访问模式默认为读写

QSharedMemory::AccessMode

QSharedMemory::ReadOnly 共享内存段是只读的。不允许写入共享内存段。尝试写入使用 ReadOnly 创建的共享内存段会导致程序中止。
QSharedMemory::ReadWrite 读取和写入共享内存段都是允许的。

基本使用流程:

 发送内容到共享内存

  1. 设置一个标识  setKey();
  2. 使用isAttached()判断进程是否与共享内存相连
  3. 使用detach()断开连接
  4. create(size)创建共享内存
  5. 上锁
  6. 将数据写入共享内存
  7. 解锁

从共享内存中读取数据:

  1. attach()连接到共享内存
  2. 上锁
  3. 读取数据
  4. 解锁

例子:写入和读取数据

    QSharedMemory memory;创建对象
    memory.setKey("1000");//设置标识

    //写入数据
    if(memory.isAttached())//已经连接的话
    {
        memory.detach();//断开连接
    }
    QString Str="SharedMemory";

    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);
    QDataStream S(&buffer);
    S<<Str;//将数据写到缓存中
    memory.create(buffer.size());//创建共享内存
    memory.lock();//上锁
    char * M=(char *)memory.data();//获取memory的指针
    const char *N=buffer.data().data();//获取缓存的指针
    memcpy(M,N,buffer.size());//把数据复制到共享内存中
    memory.unlock();//解锁

    //读取数据
    memory.attach();//连接共享内存
    QBuffer buffer1;
    QDataStream in(&buffer);
    QString Str1;

    memory.lock();//上锁
    buffer.setData((char*)memory.constData(),memory.size());//存入数据
    buffer.open(QBuffer::ReadOnly);//只读模式
    in>>Str1;//读取数据
    memory.unlock();//解锁

    memory.detach();//断开连接
    qDebug()<<Str1;

使用共享内存实现两个进程的聊天:

ui界面:

.h文件:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QSharedMemory>
#include<QBuffer>
#include<QMessageBox>
#include<QDataStream>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

    void on_pushButton_3_clicked();

private:
    Ui::Widget *ui;
    QSharedMemory sharedmemory;//共享内存
};
#endif // WIDGET_H

.cpp文件:

#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    sharedmemory.setKey("GG");//设置标识
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()//读取数据
{
    if(!sharedmemory.attach())
    {
        QMessageBox::information(this,"提示信息","连接共享内存失败",QMessageBox::Ok);
        return;
    }
    QBuffer buffer;
    QString S1;
    QDataStream in(&buffer);
    sharedmemory.lock();
    buffer.setData((char *)sharedmemory.constData(),sharedmemory.size());//设置数据
    buffer.open(QBuffer::ReadOnly);
    in>>S1;//读取数据
    sharedmemory.unlock();//解锁
    sharedmemory.detach();//断开连接
    ui->textEdit->append(QString("他人:%1").arg(S1));
}

void Widget::on_pushButton_2_clicked()//发送数据
{
    if(sharedmemory.isAttached())//内存和进程连接
    {
       if(sharedmemory.detach())//断开连接
       {
           QMessageBox::information(this,"提示信息","已断开连接");
       }
       else
       {
           QMessageBox::information(this,"提示信息","断开连接失败");
           return;
       }
    }
    if(ui->lineEdit->text().isEmpty())
    {
        QMessageBox::information(this,"提示信息","内容不能为空。",QMessageBox::Ok);
    }
    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);
    QDataStream out(&buffer);
    QString Str=ui->lineEdit->text();
    out<<Str;//把内容写入缓存区
    int size=buffer.size();
    if(!sharedmemory.create(size))
    {
        QMessageBox::information(this,"提示信息","内存创建失败",QMessageBox::Ok);
        return;
    }
    sharedmemory.lock();
    const char * Buff=buffer.data().data();//获取buffer的指针
    char *Sha=(char *)sharedmemory.data();//获取共享内存的指针
    memcpy(Sha,Buff,qMin(sharedmemory.size(),size));
    sharedmemory.unlock();//解锁
    ui->textEdit->append(QString("本人:%1").arg(ui->lineEdit->text()));//显示信息
}

void Widget::on_pushButton_3_clicked()//断开连接
{
    if(sharedmemory.detach())//断开连接
    {
        QMessageBox::information(this,"提示信息","已断开连接");
    }
}

main函数:

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w1;
    w1.setWindowTitle("widget1");
    w1.show();//进程1
    Widget w2;
    w2.setWindowTitle("widget2");
    w2.show();//进程2
    return a.exec();
}

这里解释一下为什么要有断开连接的按钮:

经过多次测试发现 :

A端发完数据,B端接收数据后,A端需要主动断开连接后B端才能正常发送数据。

(懂的大佬请在评论区解释一下)

效果:

widget2 发送信息给widget1

 记住发送端需要主动断开连接:

widget1 发送信息给 widget2

 QProcess

参考文章:关于Qt的QProcess进程间双向通信_qprocess进程间通信_weixin_46424582的博客-CSDN博客

QProcess进程间通信:

 主线程构建思路:

  • 发送数据到子进程:使用write()函数
  • 读取子进程发送的数据数据:监听readReadyStandardOutput()信号

创建一个项目:

ui界面中添加以下控件: textEdit   pushButton  lineEdit

.h文件:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QProcess>
#include<QMessageBox>
#include<QDebug>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();
private:
    Ui::Widget *ui;
    QProcess *process;
};
#endif // WIDGET_H

.cpp文件:

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("主进程");
    process=new QProcess;
    connect(process,&QProcess::readyReadStandardOutput,[=]()//读取信息
    {
        QString S=process->readAllStandardOutput().data();
        ui->textEdit->append(QString("子线程:%1").arg(S));
    });

}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_clicked()//打开子进程
{
    //子线程的开启
    process->start("D:/Qt_data/build-QProcess_text1-Desktop_Qt_5_9_9_MinGW_32bit-Debug/debug/QProcess_text1.exe");

}

void Widget::on_pushButton_2_clicked()//发送数据
{

    if(ui->lineEdit->text().isEmpty())
    {
        QMessageBox::information(this,"提示信息","输入框不能为空。",QMessageBox::Ok);
        return;
    }
    if(process->Running)
    {
        QString S=ui->lineEdit->text();//获取lineEdit中的内容
        process->write(S.toStdString().c_str());//写入数据
        ui->textEdit->append("父线程:"+S);//在聊天框显示内容
    }
    return;

}

子线程的构建思路:

  • 发送数据到父线程:使用文件打开 stdout,然后把数据写入stdout中
  • 获取父线程发送过来的数据:
    • linux中:使用QSocketNotifier 监听 stdin文件,当改文件有变化是,读取信息
    • Windows中:需要开启一个线程来管理stdin的文件变化,这个需要使用Windows API函数

这里介绍Windows中的子线程构建:

创建一个项目:

在pro文件中添加:

QT +=concurrent

ui界面中添加:

 .h文件:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QFile>
#include<QSocketNotifier>
#include<QBuffer>
#include<QMessageBox>
#include<QFuture>
#include<QtConcurrent>
#include<QIODevice>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();
    void readStdin();//读取数据

private:
    Ui::Widget *ui;
    QFile file;
signals:
    void sig_log(QString S);//显示数据
    void sig_receivedCommand(QString S);//显示数据
};
#endif // WIDGET_H

.cpp文件:

#include "widget.h"
#include "ui_widget.h"
#include<iostream>
#include<windows.h>
#include<io.h>
#include<fcntl.h>
#include<QSocketNotifier>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("子进程");

    QFuture<void> fu=QtConcurrent::run(this,&Widget::readStdin);//开启一个线程
    connect(this,&Widget::sig_receivedCommand,this,[&](QString s)
    {
        ui->textEdit->append("父线程:"+s);
    });
    connect(this,&Widget::sig_log,this,[=](QString s)
    {
        ui->textEdit->append("父线程:"+s);
    });

}

Widget::~Widget()
{
    delete ui;
}


void Widget::readStdin()//读取数据
{
    bool ok=true;
    char chbuf[1024];//缓存
    DWORD dwRead;//32位无符号整数
    HANDLE hStdinDup;//HANDLE 句柄类型

    const HANDLE hStdin=GetStdHandle(STD_INPUT_HANDLE);//GetStdHandle获取标准输入的句柄
    if(hStdin==INVALID_HANDLE_VALUE)//为无效句柄的话
        return;
    DuplicateHandle(GetCurrentProcess(),hStdin,
                    GetCurrentProcess(),&hStdinDup,0,false,DUPLICATE_SAME_ACCESS);//创建一个新句柄
    CloseHandle(hStdin);//关闭旧句柄
    while(ok)
    {
        ok=ReadFile(hStdinDup,chbuf,sizeof(chbuf),&dwRead,NULL);//读取hstdinDup句柄文件中的数据
        emit sig_log(QLatin1String("ok is:")+QString::number(ok));
        if(ok &&dwRead!=0)
        {
            emit sig_receivedCommand(QString::fromUtf8(chbuf,dwRead));//读取数据
        }
    }

}

void Widget::on_pushButton_clicked()//发送数据
{
    if(ui->lineEdit->text().isEmpty())
    {
        QMessageBox::information(this,"提示信息","输入框不能为空。",QMessageBox::Ok);
        return;
    }
    QFile fileout;
    if(fileout.open(stdout,QIODevice::WriteOnly))
    {
        QString S=ui->lineEdit->text();
        fileout.write(S.toStdString().c_str());
        ui->textEdit->append("子线程:"+S);
        fileout.close();//关闭文件
    }

}

运行效果:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt 进程间通信 的相关文章

  • QWinTaskbarProgress 不会显示

    我使用的是windows7和Qt5 3 0 我在 MainWindow 的构造函数中添加了以下内容 但任务栏上没有显示任何内容 我错过了什么 QWinTaskbarProgress pTaskbarProgress new QWinTask
  • wkhtmltopdf 修补了 qt 吗?

    我正在尝试将多个 URL 转换为 PDF 但是 当我编译 wkhtmltopdf 或运行时apt get install wkhtmltopdf并尝试一下 它说 错误 此版本的 wkhtmltopdf 是针对未修补的 QT 版本构建的 并且
  • Qt 编译器标志顺序

    我的目标是消除某些类型的编译器警告 我发现可以通过在 pro 文件中添加编译器标志来做到这一点 QMAKE CXXFLAGS Wno unused variable Wno reorder 问题是它们被添加在 Qt 构建系统生成的标志之前
  • QObject多重继承

    我正在尝试在 C Qt 类中使用 mix 来提供一大堆具有通用接口的小部件 该接口是以这样的方式定义的 如果它被定义为其他小部件类的基类 那么小部件本身将具有这些信号 class SignalInterface public QObject
  • 如何将flex和bison与Qt项目集成?

    我正在 git 源代码控制下使用 Qt4 制作 GUI 程序 Github页面 https github com vinayak garg dic sim 项目的一小部分需要扫描和解析 所以我想在项目中使用flex和bison 我能想到3种
  • 在Qt中,如何正确实现委托?

    我遵循模型 视图 控制器范例 我很确定模型和视图是正确的 但我认为我的代表做错了一些事情 一切都 有效 除了第一次单击控件只是 点亮控件 而第二次单击与之交互之外 这是代表通常的实施方式吗 我的实现需要大量的构造和销毁 由scoped pt
  • 如何在Qt3D中优化点云渲染

    我正在尝试使用 Qt3D 显示大型点云 20M pts 我第一次发现这个图书馆https github com MASKOR Qt3DPointcloudRenderer https github com MASKOR Qt3DPointc
  • C++ QT libXL 错误:“启动期间程序退出,代码为 0xc0000135”

    我正在尝试编写一个使用 libXL 的 QT 应用程序 但是当我尝试编译时 我收到一个弹出框 显示 During Startup program exited with code 0xc0000135 我已经准确地找出了哪一行导致了问题 它
  • 当给定 100k 项时,QListView 需要很长时间才能更新

    我在读取文件时遇到问题 具体是我想制作一本小字典 在我需要阅读的文件中有这样的内容 a Ph P6 a snsr CA a b c fb Dj a b c book i BS A except B gate oOPa y a font kQ
  • Qt - 意外的 GDB 退出

    我正在尝试开发一个应用程序 该应用程序创建图像并使用双线性插值填充颜色像素 然后显示它 到目前为止我的代码如下 include
  • Qt:关闭期间线程仍在运行时 qthread 被销毁

    我有一堂课 class centralDataPool public QObject Q OBJECT public centralDataPool QObject parent 0 centralDataPool commMonitor
  • 更改 Qt 中的语言环境

    我尝试使用 QLocale 和 setDefault 函数更改区域设置 但似乎不起作用 以下是使用 C 本地化库和 QLocale 更改语言环境的示例 对于 C 本地化库 它似乎可以工作 但对于 QLocale setDefault 函数调
  • Qt 码头调整大小事件

    有没有办法在 Qt 中捕捉码头的调整大小事件 我需要能够检测到扩展坞何时调整大小 而不仅仅是其位置或 功能 发生变化时 看起来 QDockWidget 没有 调整大小 信号 如果您不希望子类化以仅获得调整大小事件控件 您可以安装事件过滤器
  • 如何在Qt中更快地读取数据?

    Qt读取数据库比C 慢吗 我想我错过了一些东西 为了比较阅读速度 我在 Qt 中编写了以下内容 QElapsedTimer t t start int count 0 QString cs Driver SQL Server Server
  • 如何使用样式表删除 QWizard 中的水平线?

    我正在研究一个样式表QWizard我想删除按钮上方的水平线 我已经发布了一个最小的例子here https stackoverflow com q 52538669 8570451 这个问题是由scopchanov从最小的例子中解决的 但是
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • Qt ObjectName() 必须是唯一的吗?

    如标题所示的简单问题 如果我打电话setObjectName 在一个对象上 它是否必须是唯一的 或者只是因为约定而推荐 我已经子类化了QLabel 并希望自动为创建的对象命名 如果这是一个坏主意 我会找到一些设置随机唯一名称的方法 我实际上
  • 将 QMAKE_CXXFLAGS += -std=c++11 添加到 qt 中的 .pro 文件不起作用(在 linux 12.04 上)

    编译器输出 main o 错误 1 cc1plus 错误 无法识别的命令行选项 std c 11 解决方案是更新系统上的旧 gcc 版本 事实上 我很惊讶你的 12 04 Ubuntu 变体上有这么旧的版本 默认情况下应该有 4 6 3 您
  • 错误:命名空间“std”中没有名为“enable_if_t”的模板;您的意思是“enable_if”吗?

    我正在 macOS 10 13 6 上使用 Qt 5 11 3 进行编译 Qt使用的clang版本是 Applications Xcode app Contents Developer Toolchains XcodeDefault xct
  • 如何在 PySide/PyQt 中制作一个位于屏幕中央的小部件?

    这段代码有效 但我想知道是否有更简单的方法 def center self qr self frameGeometry cp gui QDesktopWidget availableGeometry center qr moveCenter

随机推荐

  • 政策效应,基于反事实框架

    政策效应 基于反事实框架 一 Edited by Linhao Cui 根据陈强高级计量经济学及stata应用等书籍自己整理得到 仅供学习交流使用 从一个基准的理想政策评价模型出发 Y i
  • Oracle插入或修改数据怎么也不行的解决方法

    今天在公司操作数据库 在删除一条数据的时候忘记提交事务了 之后就去添加别的了 但是后来发现怎么也添加不上 所以觉的是事务锁住了 1 直接判断未提交事务引起的表的行锁 1 1判断哪个SESSION执行了DML Insert Update De
  • C语言-蓝桥杯-算法训练 印章

    问题描述 共有 n 种图案的印章 每种图案的出现概率相同 小A买了 m 张印章 求小A集齐 n 种印章的概率 输入格式 一行两个正整数n和m 输出格式 一个实数P表示答案 保留4位小数 样例输入 2 3 样例输出 0 7500 解题思路 共
  • PPTP穿透NAT之深入分析

    PPTP穿透NAT之深入分析 bytxl的专栏 CSDN博客大家好 现在是人静时分 我公司人员都以溜光 只有我还在面对computer 在经过不解 迷惑 结论之后 现与大家分享结果 感谢朋友Zyliday 见贤思齐的实验帮助 在研究技术原理
  • URP自定义后处理(相机滤镜)

    前言 之前做游戏一直想弄个可以实时触发相机滤镜的效果 自处找了教程和资料 想要做到自定义效果的话最好办法是在unity 内部实现 这个办法比较硬核 其实不适合我这样的小白 所以我在实现的过程中非常痛苦 我用的unity URP 模式其实自带
  • OMG!解释执行java字节码文件的命令

    美团一面 收到了HR的信息 通知我去面试 说实话真的挺紧张的 自己准备了近一个月的时间 很担心面试不过 到时候又后悔不该 裸辞 自我介绍 spring的IOC AOP原理 springmvc的工作流程 handlemapping接收的是什么
  • python中的list格式化输出

    在使用python时 我们经常会用到列表 list 由于它可以保存不同类型的数据 因此很多场景下我们都会使用它来保存数据 在写代码的过程中我们经常想要显示list的内容 直接调用print又会显得很丑 还会带着方括号 和逗号 这个太丑 又不
  • Hive数据库连接-连接池实现

    Hive数据库连接 连接池实现 通过HiveJDBC获取Hive的连接Connection 下面我们简单介绍HiveJDBC数据库连接实现 HiveJDBC配置文件 连接池配置文件hive jdbc properties 初始化连接池数 d
  • Linux运维跳槽必备的40道面试精华题

    1 什么是运维 什么是游戏运维 1 运维是指大型组织已经建立好的网络软硬件的维护 就是要保证业务的上线与运作的正常 在他运转的过程中 对他进行维护 他集合了网络 系统 数据库 开发 安全 监控于一身的技术 运维又包括很多种 有DBA运维 网
  • 鼠标点击获得opencv图像坐标和像素值

    目录 一 核心函数 二 在类中定义并且使用 1 将回调函数直接声明为友元函数 2 h 3 DW S OnMou cpp 4 main cpp 三 函数调用 1 OnMouse h 2 OnMouse cpp 一 核心函数 setMouseC
  • 如何在没有 USB 数据线的情况下使用 Android Studio 在手机中安装 Android

    背景 如何在没有 USB 数据线的情况下使用 Android Studio 在手机中安装 Android 应用程序 运行调式一个Android项目 写下必要的代码后 接下来的任务是在模拟器或手机上运行应用程序 测试应用程序是否正常 及deb
  • python numpy中对ndarry按照index(位置下标)增删改查

    在numpy中的ndarry是一个数组 因此index就是位置下标 注意下标是从0开始 增加 在插入时使用np insert 在末尾添加时使用np append 删除 需要使用np delete 修改 直接指定下标 查找 直接指定下标 示例
  • 【Shell】find文件查找

    语法格式 find 路径 选项 操作 选项参数对照表 常用选项 name 查找 etc目录下以conf结尾的文件ind etc nam iname 查找当前目录下文件名为aa的文件 不区分大小写 find iname aa user 查找文
  • [激光原理与应用-69]:激光焊接的10大常见缺陷及解决方法

    激光焊接是一种以高能量密度的激光束作为热源的高效精密焊接方法 如今 激光焊接已广泛应用于各个行业 如 电子零件 汽车制造 航空航天等工业制造领域 但是 在激光焊接的过程中 难免会出现一些缺陷或次品 只有充分了解这些缺陷并学习如何避免它们 才
  • 九轴传感器之测试篇

    关于九轴传感器的数据测试处理
  • CORS与CSRF

    本文首发于我的Github博客 本篇文章介绍了CORS和CSRF的概念 作者前几天在和带佬们聊天的时候把两个概念搞混了 所以才想要了解 简单来说 CORS Cross Origin Resource Sharing 跨域资源分享 是一种机制
  • (1)基础学习——图解pin、pad、port、IO、net 的区别

    本文内容有参考多位博主的博文 综合整理如下 仅做和人学习记录 如有专业性错误还请指正 谢谢 参考1 芯片资料中的pad和pin的区别 imxiangzi的博客 CSDN博客 pin和pad的区别 参考2
  • IntelliJ IDEA 运行卡顿解决方案

    IntelliJ IDEA 运行卡顿解决方案 1 开启IntelliJ IDEA缓慢 想要提升启动速度 则打开D JetBrains IntelliJ IDEA 2020 3 2 bin 依据实际安装路径 目录下对应文件idea64 exe
  • 对csv文件,又get了新的认知

    背景 在数据分析时 有时我们会碰到csv格式文件 需要先进行数据处理 转换成所需要的数据格式 然后才能进行分析 业务侧的同学可能对Excel文件比较熟悉 Excel可以把单个sheet直接保存为csv文件 也可以直接读取csv文件 变成Ex
  • Qt 进程间通信

    Qt进程间通信的方法 TCP IP Local Server Socket 共享内存 D Bus Unix库 QProcess 会话管理 TCP IP 使用套接字的方式 进行通信 之前介绍了 这里就不介绍了 Local Server Soc