Building a Reusable Login Component in Qt

Component Requirements Analysis

Designing a login dialog involves creating a software module that is portable across different projects. The primary objective is to capture user credentials securely. Beyond basic input, the component should support auxiliary features such as random verification codes (CAPTCHA) to enhance security.

Architecture and Data Exchange

To facilitate communication between the login interface and the main application window, data encapsulation is reuqired. The standard approach involves storing user input in private member variabels within the dialog class. These value are then exposed to the parent window through public accessor methods. This ensures that the main window only receives data when the user explicitly confirms the login action.

Code Implementation

LoginDialog Header

#ifndef LOGINDIALOG_H
#define LOGINDIALOG_H

#include <QDialog>
#include <QLineEdit>
#include <QPushButton>
#include <QLabel>

class LoginDialog : public QDialog
{
    Q_OBJECT

public:
    explicit LoginDialog(QWidget *parent = nullptr);
    
    QString getUsername() const;
    QString getPassword() const;

private slots:
    void onConfirm();
    void onCancel();

private:
    void initializeUI();

    QLabel *m_usernameLabel;
    QLabel *m_passwordLabel;
    QLineEdit *m_usernameInput;
    QLineEdit *m_passwordInput;
    QPushButton *m_confirmButton;
    QPushButton *m_abortButton;

    QString m_storedUser;
    QString m_storedPass;
};

#endif // LOGINDIALOG_H

LoginDialog Implementation

#include "LoginDialog.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QFormLayout>

LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent)
{
    initializeUI();
    setWindowTitle("User Authentication");
    setFixedSize(320, 160);
}

void LoginDialog::initializeUI()
{
    m_usernameLabel = new QLabel("Account:", this);
    m_passwordLabel = new QLabel("Secret:", this);
    
    m_usernameInput = new QLineEdit(this);
    m_passwordInput = new QLineEdit(this);
    m_passwordInput->setEchoMode(QLineEdit::Password);

    m_confirmButton = new QPushButton("Sign In", this);
    m_abortButton = new QPushButton("Exit", this);

    // Using Layout Managers instead of absolute positioning
    QFormLayout *formLayout = new QFormLayout();
    formLayout->addRow(m_usernameLabel, m_usernameInput);
    formLayout->addRow(m_passwordLabel, m_passwordInput);

    QHBoxLayout *btnLayout = new QHBoxLayout();
    btnLayout->addStretch();
    btnLayout->addWidget(m_abortButton);
    btnLayout->addWidget(m_confirmButton);

    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->addLayout(formLayout);
    mainLayout->addLayout(btnLayout);

    connect(m_confirmButton, &QPushButton::clicked, this, &LoginDialog::onConfirm);
    connect(m_abortButton, &QPushButton::clicked, this, &LoginDialog::onCancel);
}

void LoginDialog::onConfirm()
{
    m_storedUser = m_usernameInput->text().trimmed();
    m_storedPass = m_passwordInput->text();

    done(QDialog::Accepted);
}

void LoginDialog::onCancel()
{
    done(QDialog::Rejected);
}

QString LoginDialog::getUsername() const
{
    return m_storedUser;
}

QString LoginDialog::getPassword() const
{
    return m_storedPass;
}

Main Window Header

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QWidget>
#include <QPushButton>
#include "LoginDialog.h"

class MainWindow : public QWidget
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);

private slots:
    void showLoginScreen();

private:
    QPushButton *m_launchButton;
};

#endif // MAINWINDOW_H

Main Window Implementation

#include "MainWindow.h"
#include <QDebug>
#include <QVBoxLayout>

MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
{
    m_launchButton = new QPushButton("Open Login", this);
    
    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->addWidget(m_launchButton);
    
    connect(m_launchButton, &QPushButton::clicked, this, &MainWindow::showLoginScreen);
}

void MainWindow::showLoginScreen()
{
    LoginDialog dlg(this);
    
    if (dlg.exec() == QDialog::Accepted) {
        qDebug() << "User ID:" << dlg.getUsername();
        qDebug() << "Password:" << dlg.getPassword();
    }
}

Enhanced Validation Logic

To make the component robust, additional validation logic should be implemented within the confirmation handler.

1. Empty Field Checks: Before calling accept(), the application should verify that both the username and password fields contain text. If either is empty, a warning message should be displayed, and the dialog should remain open.

2. Random Verification Code: Implementing a CAPTCHA requires generating a random alphanumeric string when the dialog initializes. This string is displayed on a label. When the user attempts to log in, their input is compared against this generated string. If the verification fails, an error is triggered, and the code is regenerated to prevent brute-force attempts.

Tags: Qt C++ gui Dialog Validation

Posted on Mon, 14 Sep 2026 16:19:36 +0000 by mrdamien