Qt开发图形界面上位机软件显示通过TCP接受数据图像,执行bash命令启动Geant 4

图像界面上位机软件

上位机软件功能

本人设计的上位机主要分为信号图像显示区、按键和参数设置区和文字信息区三大部分。 整个上位机软件主要分为三部分: 1. 启动和关闭 Geant4 物理仿真软件并且设置相关参数。 2. 显示探测器能量沉积数字信号。 3. 显示 TCP连接状态信息和 Geant 4 探测器能量沉积。

但是有一点我很不理解,为了实现每次接收到TCP数据帧,都能够更新信号图像,我把new空间放到了header文件中,在cpp文件的doProcessNewConnect函数中怎么都没有办法实现。本人觉得这是不好的编程习惯但是也是无奈之举。。。如果你知道欢迎回复!

mainwindow.h

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void begin_G4();
    void Qt_Tcp();
    void receive();
    void doProcessNewConnect(QByteArray);

    DataTable generateRandomData(int listCount, int valueMax, int valueCount) const;

    QTcpServer *TcpServer;
    QTcpSocket *TcpSocket;
    QChart *chart = new QChart();
    QLineSeries *series2 = new QLineSeries(chart); //初始化一条折线  chart
    QChartView *chartView = new QChartView(chart);
    QVBoxLayout * pre;
    QByteArray array1;
    
    QProcess *poc;
    QByteArray output1;
    QString str_output1;
    void on_readoutput();

private slots:

    void on_pushButton_close_clicked();

private:
    Ui::MainWindow *ui;
};

mianwindows.cpp

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->spinBox->setValue(1);
    ui->spinBox_2->setValue(1);
    //TCP Server
    //指定父对象,让其自动回收空间
    TcpServer = NULL;
    TcpSocket = NULL;
    TcpServer = new QTcpServer();
    TcpServer->listen(QHostAddress::Any, 8000);
    if(!TcpServer)//服务器打开失败
    {
        ui->textEdit->append("cannot open the TCP server!");//追加显示
        ui->textEdit->append("\n");
        return;
    }
    setWindowTitle("server port : 8000");
    connect(TcpServer, &QTcpServer::newConnection,
            this, &MainWindow::receive);
    connect(ui->pushButton_begin, &QPushButton::pressed, this, &MainWindow::begin_G4);
    //ui->pushButton信号发出者,&QPushButton::pressed 处理信号,发送者的类名::信号名字
    //this 信号接受者
    //&MainWindow::begin_G4槽函数,信号处理函数  接受者类名::槽函数名字
    connect(poc, &QProcess::readyReadStandardOutput,
            this, &MainWindow::on_readoutput);    
}

void MainWindow::receive()
{
    //取出建立好连接的套接字
    TcpSocket = TcpServer->nextPendingConnection();
    QString ip = TcpSocket->peerAddress().toString();
    qint16 port1 = TcpSocket->peerPort();
    QString port2 = QString::number(port1);
    ui->textEdit->append("Tcp client address :");
    ui->textEdit->append(ip);
    ui->textEdit->append("\n");
    ui->textEdit->append("Tcp client port :");
    ui->textEdit->append(port2);
    ui->textEdit->append("\n");

    connect(TcpSocket, &QTcpSocket::readyRead, this,
            &MainWindow::read_data);

}

void MainWindow::read_data()
{
    array_read_data = TcpSocket->readAll();
    doProcessNewConnect(array_read_data);
    array_read_data.clear();
}

void MainWindow::doProcessNewConnect(QByteArray array1)
{
    QList<QPointF> Data2;
    QPointF point1;
   //int nameIndex = 0;
    int number1 = 0;  //读取出TCP帧中传输的数据量
    for(int ii=0;ii<3;ii++)
    { //把ASII码转换为int类型
        number1 += (array1[ii]-48) * qPow(10, 2-ii);
    }
    int gg=3;
    int sequence = 9;
    ui->textEdit->append("energy deposition :");
    for(int nn=0; nn<number1; nn++)
      {
          QByteArray array3;
          float number4 = 0.0;  
          int number3[3];
          for(int mm=0; mm<3; mm++)
          {
              number3[mm] = array1[gg+mm] - 48;
              number4 += (array1[gg+mm] - 48) * qPow(10, -mm);
              qDebug()<<"number4 = "<<number4;
              QString data = QString("float is %1").arg(number4);
              ui->textEdit->append(data);
          }
          qDebug()<<"QByteArray number3 : "
           <<number3[0]
           <<number3[1]
           <<number3[2];
          //qDebug()<<"number4="<<number4;
          point1.setX(sequence);
          point1.setY(number4);
          Data2.append(point1);
          if(nn%5==0) sequence += 6;
          else if(nn%5==1) sequence +=5;
          else if(nn%5==2) sequence +=7;
          else if(nn%5==3) sequence +=6;
          else if(nn%5==4) sequence +=5;
          gg +=3;
      }
   chart->addSeries(series2);//chart中添加一条折线
   QString name("energy deposition ");
   series2->setName(name);//折线设置名字
   series2->replace(Data2);
   chart->createDefaultAxes();// 创建坐标
   chart->axes(Qt::Vertical).first()->setRange(0, 10);//设置纵坐标范围
   // Add space to label to add space between labels and axis
   QValueAxis *axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first());
   //利用qobject_cast进行安全转换,将QAbstractAxis类型的变量转换为QVasequencelueAxis,为的是在下面使用->setLabelFormat("%.1f  ")
   Q_ASSERT(axisY);//当axisY == 0时,程序会中断
   axisY->setLabelFormat("%.2f  ");//设置坐标的值精确到小数点后2位
   //chart->legend()->hide();//隐藏图例
   chart->legend()->setAlignment(Qt::AlignTop);//设置图例位置在顶部
   chart->setAnimationOptions(QChart::GridAxisAnimations);//设置动画效果,在第一次显示图表或者更改图标区域大小的时候会显示动画效果
   chart->axes(Qt::Horizontal).first()->setRange(0, sequence);//设置横坐标范围
   //ui->widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
   pre = ui->verticalLayout;  //new QVBoxLayout(ui->widget)
   pre->addWidget(chartView);
}

void MainWindow::begin_G4()
{
    //spinbox
    QString detector_number;
    ui->spinBox->setValue(55);
    ui->spinBox->setRange(1, 100);
    ui->spinBox->setSingleStep(1);
    ui->spinBox->setWrapping(true);
    //get the number
    detector_number = ui->spinBox->text();

    //spinbox
    QString emitted_particle;
    ui->spinBox_2->setRange(1, 10000);
    ui->spinBox_2->setSingleStep(1);

    ui->spinBox_2->setWrapping(true);
    //get the number
    emitted_particle = ui->spinBox_2->text();

    //新建run_mao.mac文件,并且执行,每次对文件覆盖之后重新写入
    QFile file("/home/zx/maojunjie/NeutronSource/build/run_mao.mac");
    //(/home/zx/maojunjie/NeutronSource/build/run_mao.mac, D:/run_mao.mac)
    file.open(QIODevice::WriteOnly | QIODevice::Text);
    QString a1 = "/control/verbose 2\r\n";
    file.write(a1.toUtf8());
    QString a2 = "/run/verbose 1\r\n";
    file.write(a2.toUtf8());
    QString a3 = "/testhadr/stepping/seDSN " + detector_number + "\r\n";
    file.write(a3.toUtf8());
    QString a4 = "/run/initialize\r\n";
    file.write(a4.toUtf8());
    QString a5 = "/process/list\r\n";
    file.write(a5.toUtf8());
    QString a6 = "/gun/particle ion\r\n";
    file.write(a6.toUtf8());
    QString a7 = "/gun/ion 95 241\r\n";
    file.write(a7.toUtf8());
    QString a8 = "/gun/energy 0. eV\r\n";
    file.write(a8.toUtf8());
    QString a9 = "/run/printProgress " + emitted_particle + "\r\n";
    file.write(a9.toUtf8());
    QString a10 = "/run/beamOn " + emitted_particle + "\r\n";
    file.write(a10.toUtf8());
    file.close();
    
    //启动bash命令,写入命令并且执行,启动Geant 4物理仿真软件
    poc->start("bash");
    poc->waitForFinished();

    poc->write("source /home/zx/Main_Install/geant4.10.05.p01-install/bin/geant4.sh\n");
    poc->waitForFinished();
	
    poc->write("cd /home/zx/maojunjie/NeutronSource/build\n");

    poc->write("./NeutronSource run_mao.mac\n");
}

//读取运行bash的信息
void MainWindow::on_readoutput()
{
    ui->textEdit->append(poc->readAllStandardOutput().data());
}

上位机软件界面

在Ubuntu中,你可以使用FFmpeg将摄像头捕获到的视频流传输到上位机,并在Qt应用程序中实时显示。这可以通过以下几个步骤实现: 1. **安装FFmpeg**: 首先确保FFmpeg已经安装在系统中。如果没有,可以使用`sudo apt-get install ffmpeg`命令进行安装。 2. **设置视频捕捉**: 使用FFmpeg的`v4l2src`或`video4linux2`设备节点从摄像头获取视频数据。例如: ```bash ffmpeg -i /dev/video0 -f mjpeg -r 30 out.mjpeg ``` 这里假设摄像头设备路径为`/dev/video0`,`-r 30`指定帧率。 3. **创建UDP服务器接收视频流**: 如果上位机通过UDP协议接收视频,可以使用FFmpeg的`-f mpegts`选项并将输出重定向到一个UDP地址,如: ```bash ffmpeg -i ... -f mpegts udp://<your-uplink-ip>:<port> ``` 4. **在Qt显示视频**: 使用QML(Qt Quick)或者Qt的`QVideoWidget`在Qt应用中显示接收到的视频。在Qt中,你需要编写一个接受并处理网络数据的部分,然后利用`QMediaPlayer`连接到视频源。 ```cpp QMediaPlayer mediaPlayer; mediaPlayer.setMedia(QMediaContent(QUrl("udp://<your-uplink-ip>:<port>"))); mediaPlayer.play(); QQuickView view; view.rootContext()->setContextProperty("player", &mediaPlayer); ``` 5. **构建Qt界面**: 创建一个包含`QVideoWidget`的UI设计,并确保它与播放器实例关联起来。 **相关问题--:** 1. 如何在Qt中处理FFmpeg的错误或异常? 2. 如何确保视频传输质量和稳定性? 3. 是否需要考虑版权问题以及使用FFmpeg的许可协议?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值