QT-图片浏览器(显示器)的实现(含登录界面)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QT-图片浏览器(显示器)的实现(含登录界面)相关的知识,希望对你有一定的参考价值。

一、设计要求

1、登录界面

​ 创建一个窗体,设计用户登录的界面(含有用户名、密码),并实现用户登录的功能,要求用户提交的登录按钮时能获取界面中的用户名、密码数据并与数据库中的数据进行匹配,若用户名,密码正确则登录成功,否则登录失败。

2、功能主界面

​ 功能主界面需要具备显示打开的文件路径和文件名的功能,并且可以选择需要打开的图片并显示到此界面上。

二、具体实现过程

1、图片演示

2、详细代码实现

主函数 man.c
#include "dialog.h"
#include <QApplication>

int main(int argc, char *argv[])

    QApplication a(argc, argv);
    Dialog w;
    w.show();

    return a.exec();

(1)登录界面代码实现

1.dialog.cpp: (登录界面.cpp文件)
#include "dialog.h"
#include "ui_dialog.h"
#include "zhu.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)

    ui->setupUi(this);
    this->setWindowTitle("LoginInterface");    //设置登录界面标题
    this->setWindowIcon(QIcon(":/pikapika.ico"));  //设置登录标题图像


Dialog::~Dialog()

    delete ui;


void Dialog::on_login_clicked()

    if((ui->lineEdit->text() == "ZW") && (ui->lineEdit_2->text() == "123456"))  //判断账号和密码
    
    close();  //进入功能界面并关闭登录界面
    zhu obj;
    obj.exec();  //进入功能界面
    


void Dialog::on_regi_clicked()  //注册功能没有实现,点击注册则是关闭登录界面

    reject();  //拒绝
    //close();

		
2. dialog.h: (登录界面头文件)
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QDebug>

namespace Ui 
class Dialog;

class Dialog : public QDialog

    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
    
private slots:
    void on_login_clicked();
    void on_regi_clicked();
private:
    Ui::Dialog *ui;
;

#endif // DIALOG_H

(2)功能界面代码实现

1.zhu.c (功能界面.cpp文件)
#include "zhu.h"
#include "ui_zhu.h"
#include <QFileDialog>
#include <QDebug>
zhu::zhu(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::zhu)

    ui->setupUi(this);
    this->resize(463,603);  //设置界面大小属性
    this->setWindowTitle("PicturrBrowser"); //设置界面标题
    this->setWindowIcon(QIcon(":/zhujiemian.ico"));  //设置界面标题图标 ,双引号内为图片地址


zhu::~zhu()

    delete ui;


void zhu::on_pushButton_clicked()

    QString filename = QFileDialog::getOpenFileName(this,
                                                    "Picture Browser",
                                                    QDir::currentPath(),
                                                    "所有图片(*.emf;*.wmf;*.jpg;*.jpeg;*.jpe;*.png;*.bmp;*.gif;*.tif;*.tiff;*.wdp;*.svg)"
                                                    );  //打开一个消息框 选择图片 第二个参数为打开地址,用此参数为当前路径
    if(filename.isEmpty())
           return;
    ui->lineEdit->setText(filename);  //将获取的文件名写到单行文本框上

    //label显示图片
    QPixmap pixmap;//保存图片像素点
    pixmap.load(filename);//加载图片
    ui->label->setPixmap(pixmap);//显示图片
    ui->label->setScaledContents(true);//内容自适应

2.zhu.h (功能界面.h 头文件)
#ifndef ZHU_H
#define ZHU_H

#include <QDialog>

namespace Ui 
class zhu;


class zhu : public QDialog

    Q_OBJECT

public:
    explicit zhu(QWidget *parent = 0);
    ~zhu();

private slots:
    void on_pushButton_clicked();

private:
    Ui::zhu *ui;
;

#endif // ZHU_H

三、总结(博主有话要bb~~)

​ 此项目是通过QT采用c++的编程语言编写,具体代码含义和逻辑思路代码注释中已经交代清楚,如果有想深入了解的好兄弟可以通过评论或者私信我哦~

​ 账号和密码可以预先写入源代码中,也可以通过注册按钮设置槽函数,将注册的账号密码用数据库存储,在登录时用获取的账号密码与数据库中的数据进行比对。

​ 由于篇幅有限(博主水平有限Q-Q),在本实验中采用事先预设账号密码的形式,方便大家了解,具体的注册功能将会在后面的博客中更新,大家可以三连加关注,博主会更新更多的好玩的知识给大家分享哟~

qt的udp的初步使用

该程序实现的功能是:局域网内,每个用户登录到聊天软件,则软件界面的右端可以显示在线用户列表,分别显示的是用户名,主机名,ip地址。软件左边那大块是聊天内容显示界面,这里局域网相当于qq中的qq群,即群聊。每个人可以在聊天输入界面中输入文字并发送。其聊天界面如下:

    

     该程序实现的是每个用户登录既是客户端又是服务器端,这就需要看你站在哪个角度看问题了。简单的说,当用户发送信息给别人时就是客户端,当接收别人的信息是就可以看做是服务器端。

  下面分服务器端和客户端2部分来介绍。

  服务器端:建立一个UDP Socket并绑定在固定端口后,用信号与槽的方式进行监听是否有数据来临。如果用,接收其数据并分析数据的消息类型,如果消息是新用户登录则更新用户列表并在聊天显示窗口中添加新用户上线通知;同理,如果是用户下线,则在用户列表中删除该用户且在聊天显示窗口中显示下线通知;如果是聊天消息,则接收该消息并且在窗口中显示。其流程图如下:

    

  客户端:首先当客户端登录时,获取本机的用户名,计算机名和ip地址,并广播给局域网的服务器更新用户列表。然后当客户端需要发送信息时,则在聊天输入栏中输入信息并按发送键发送聊天内容,当然于此同时也广播本地系统的各种信息。其流程图如下:

   

  程序主要代码和注释如下:

widget.h:

复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
class QUdpSocket;

namespace Ui {
class Widget;
}

// 枚举变量标志信息的类型,分别为消息,新用户加入,用户退出,文件名,拒绝接受文件
enum MessageType{Message, NewParticipant, ParticipantLeft, FileName, Refuse};


class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void newParticipant(QString userName,
                        QString localHostName, QString ipAddress);
    void participantLeft(QString userName,
                         QString localHostName, QString time);
    void sendMessage(MessageType type, QString serverAddress="");

    QString getIP();
    QString getUserName();
    QString getMessage();

private:
    Ui::Widget *ui;
    QUdpSocket *udpSocket;
    qint16 port;

private slots:
    void processPendingDatagrams();

    void on_sendButton_clicked();
};

#endif // WIDGET_H
复制代码

widget.cpp:

复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QUdpSocket>
#include <QHostInfo>
#include <QMessageBox>
#include <QScrollBar>
#include <QDateTime>
#include <QNetworkInterface>
#include <QProcess>


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

    udpSocket = new QUdpSocket(this);//创建一个QUdpSocket类对象,该类提供了Udp的许多相关操作
    port = 45454;
    //此处的bind是个重载函数,连接本机的port端口,采用ShareAddress模式(即允许其它的服务连接到相同的地址和端口,特别是
    //用在多客户端监听同一个服务器端口等时特别有效),和ReuseAddressHint模式(重新连接服务器)
    udpSocket->bind(port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
    //readyRead()信号是每当有新的数据来临时就被触发
    connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));
    sendMessage(NewParticipant);//打开软件时就向外发射本地信息,让其他在线用户得到通知
}

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

// 使用UDP广播发送信息,MessageType是指头文件中的枚举数据类型
//sendMessage即把本机的主机名,用户名+(消息内容后ip地址)广播出去
void Widget::sendMessage(MessageType type, QString serverAddress)
{
    QByteArray data;    //字节数组
    //QDataStream类是将序列化的二进制数据送到io设备,因为其属性为只写
    QDataStream out(&data, QIODevice::WriteOnly);
    QString localHostName = QHostInfo::localHostName();//返回主机名,QHostInfo包含了一些关于主机的静态函数
    QString address = getIP();    //调用自己类中的getIP()函数
    //将type,getUserName(),localHostName按照先后顺序送到out数据流中,消息类型type在最前面
    out << type << getUserName() << localHostName;

    switch(type)
    {
    case Message :
        if (ui->messageTextEdit->toPlainText() == "") {    //将输入框里的文字转化成纯文本发送
            //当发送的文本为空时创建一个警告信息窗口,tr函数为译本函数,即译码后面的text内容
            QMessageBox::warning(0,tr("警告"),tr("发送内容不能为空"),QMessageBox::Ok);    
            return;
        }
        out << address << getMessage();//将ip地址和得到的消息内容输入out数据流
        ui->messageBrowser->verticalScrollBar()    //返回垂直条
                ->setValue(ui->messageBrowser->verticalScrollBar()->maximum());//设置垂直滑动条的最大值
        break;

    case NewParticipant :
        out << address;    //为什么此时只是输出地址这一项呢?因为此时不需要传递聊天内容
        break;

    case ParticipantLeft :
        break;

    case FileName :
        break;

    case Refuse :
        break;
    }
    //一个udpSocket已经于一个端口bind在一起了,这里的data是out流中的data,最多可以传送8192个字节,但是建议不要超过
    //512个字节,因为这样虽然可以传送成功,但是这些数据需要在ip层分组,QHostAddress::Broadcast是指发送数据的目的地址
    //这里为本机所在地址的广播组内所有机器,即局域网广播发送
    udpSocket->writeDatagram(data,data.length(),QHostAddress::Broadcast, port);//将data中的数据发送
}

// 接收UDP信息
void Widget::processPendingDatagrams()
{
    //hasPendingDatagrams返回true时表示至少有一个数据报在等待被读取
    while(udpSocket->hasPendingDatagrams())
    {
        QByteArray datagram;
        //pendingDatagramSize为返回第一个在等待读取报文的size,resize函数是把datagram的size归一化到参数size的大小一样
        datagram.resize(udpSocket->pendingDatagramSize());
        //将读取到的不大于datagram.size()大小数据输入到datagram.data()中,datagram.data()返回的是一个字节数组中存储
        //数据位置的指针
        udpSocket->readDatagram(datagram.data(), datagram.size());
        QDataStream in(&datagram, QIODevice::ReadOnly);//因为其属性为只读,所以是输入
        int messageType;    //此处的int为qint32,在Qt中,qint8为char,qint16为uint
        in >> messageType;    //读取1个32位长度的整型数据到messageTyep中
        QString userName,localHostName,ipAddress,message;
        QString time = QDateTime::currentDateTime()
                .toString("yyyy-MM-dd hh:mm:ss");//将当前的时间转化到括号中的形式

        switch(messageType)
        {
        case Message:
            //in>>后面如果为Qstring,则表示读取一个直到出现\'\\0\'的字符串
            in >> userName >> localHostName >> ipAddress >> message;
            ui->messageBrowser->setTextColor(Qt::blue);//设置文本颜色
            ui->messageBrowser->setCurrentFont(QFont("Times New Roman",12));//设置字体大小
       //     ui->messageBrowser->append("[ " +userName+" ] "+ time);//输出的格式为用户名加时间显示
            //输出的格式为主机名加时间显示,但输出完后为什么会自动换行呢?
            ui->messageBrowser->append("[ " +localHostName+" ] "+ time);
            ui->messageBrowser->append(message);//消息输出
            break;

        case NewParticipant:
            in >>userName >>localHostName >>ipAddress;
            newParticipant(userName,localHostName,ipAddress);
            break;

        case ParticipantLeft:
            in >>userName >>localHostName;
            participantLeft(userName,localHostName,time);
            break;

        case FileName:
            break;

        case Refuse:
            break;
        }
    }
}

// 处理新用户加入
void Widget::newParticipant(QString userName, QString localHostName, QString ipAddress)
{
    //此处的findItems表示找到与内容localHostName匹配的item,其匹配是基于变体的匹配模式
    bool isEmpty = ui->userTableWidget->findItems(localHostName, Qt::MatchExactly).isEmpty();
    if (isEmpty) {    //没有找到相应的主机名
        //新建3个小的item,分别为user,host,ip
        QTableWidgetItem *user = new QTableWidgetItem(userName);
        QTableWidgetItem *host = new QTableWidgetItem(localHostName);
        QTableWidgetItem *ip = new QTableWidgetItem(ipAddress);

        ui->userTableWidget->insertRow(0);//先设置的是第0行,即新来的用户放在最上面
        ui->userTableWidget->setItem(0,0,user);//第0行的第1列...
        ui->userTableWidget->setItem(0,1,host);
        ui->userTableWidget->setItem(0,2,ip);
        ui->messageBrowser->setTextColor(Qt::gray);
        ui->messageBrowser->setCurrentFont(QFont("Times New Roman",10));
        //arg为返回后面文本的一个副本,%1表示输出的内容按照第1个.arg后面的输出?
        ui->messageBrowser->append(tr("%1 在线!").arg(userName));
        ui->userNumLabel->setText(tr("在线人数:%1").arg(ui->userTableWidget->rowCount()));//在线人数为条目的行数

        sendMessage(NewParticipant);//该句的功能是让新来的用户也能收到其它在线用户的信息,可拥于更新自己的好友列表
    }
}

// 处理用户离开
void Widget::participantLeft(QString userName, QString localHostName, QString time)
{
    //找到第一个对应的主机名
    int rowNum = ui->userTableWidget->findItems(localHostName, Qt::MatchExactly).first()->row();
    ui->userTableWidget->removeRow(rowNum);    //此句执行完后,rowCount()内容会自动减1
    ui->messageBrowser->setTextColor(Qt::gray);//设置文本颜色为灰色
    ui->messageBrowser->setCurrentFont(QFont("Times New Roman", 10));
    ui->messageBrowser->append(tr("%1 于 %2 离开!").arg(userName).arg(time));
    ui->userNumLabel->setText(tr("在线人数:%1").arg(ui->userTableWidget->rowCount()));
}

// 获取ip地址,获取本机ip地址(其协议为ipv4的ip地址)
QString Widget::getIP()
{
    //QList是Qt中一个容器模板类,是一个数组指针?
    QList<QHostAddress> list = QNetworkInterface::allAddresses();//此处的所有地址是指ipv4和ipv6的地址
    //foreach (variable, container),此处为按照容器list中条目的顺序进行迭代
    foreach (QHostAddress address, list) {    
        if(address.protocol() == QAbstractSocket::IPv4Protocol)
            return address.toString();
    }
    return 0;
}

// 获取用户名
QString Widget::getUserName()
{
    QStringList envVariables;
    //将后面5个string存到envVariables环境变量中
    envVariables << "USERNAME.*" << "USER.*" << "USERDOMAIN.*"
                 << "HOSTNAME.*" << "DOMAINNAME.*";
    //系统中关于环境变量的信息存在environment中
    QStringList environment = QProcess::systemEnvironment();
    foreach (QString string, envVariables) {
        //indexOf为返回第一个匹配list的索引,QRegExp类是用规则表达式进行模式匹配的类
        int index = environment.indexOf(QRegExp(string));
        if (index != -1) {
            //stringList中存的是environment.at(index)中出现\'=\'号前的字符串
            QStringList stringList = environment.at(index).split(\'=\');
            if (stringList.size() == 2) {
                return stringList.at(1);//at(0)为文字"USERNAME.",at(1)为用户名
                break;
            }
        }
    }
    return "unknown";
}

// 获得要发送的消息
QString Widget::getMessage()
{
    QString msg = ui->messageTextEdit->toHtml();//转化成html语言进行发送

    ui->messageTextEdit->clear();//发送完后清空输入框
    ui->messageTextEdit->setFocus();//重新设置光标输入焦点,即焦点保持不变
    return msg;
}


// 发送消息
void Widget::on_sendButton_clicked()
{
    sendMessage(Message);
}
复制代码

main:

复制代码
#include <QtGui/QApplication>
#include "widget.h"
#include <QTextCodec>    //处理不同语言编码的类

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QTextCodec::setCodecForTr(QTextCodec::codecForLocale());//对不同的文字选择不同的编码
    Widget w;
    w.show();

    return a.exec();
}

以上是关于QT-图片浏览器(显示器)的实现(含登录界面)的主要内容,如果未能解决你的问题,请参考以下文章

Fdog系列:使用Qt模仿QQ实现登录界面到主界面,功能篇。

Fdog系列:使用Qt模仿QQ实现登录界面到主界面,功能篇。

QT 做图片缩略显示 滚动条下拉 怎么实现动态加载下面的图片?

Qt 之 模仿 QQ登陆界面——样式篇

qt的udp的初步使用

Qt项目实战2:简单的图片查看器