QtコンポーネントUIにおけるレイアウト状態の永続化手法

レイアウト状態の永続化

優れたソフトウェアは機能性だけでなく、ユーザーインターフェースの一貫性が重要です。アプリケーション終了時にUI状態を保存し、次回起動時に復元する「レイアウト記憶」機能は、ユーザビリティ向上に不可欠です。

実装概要

レイアウト記憶機能は次の流れで実装します:

  1. 終了時: UI状態をシリアライズして保存
  2. 起動時: 保存データをデシリアライズして復元

主要コンポーネント

ウィンドウ管理

複数ウィンドウの生成・破棄を一元管理します。各ウィンドウは独立したコンポーネントとして動作します。

タブ制御

タブシステムでは:

  • 同時に選択可能なタブは1つのみ
  • ドラッグによるタブ再配置をサポート

サブパネル

各タブに対応するコンテンツ領域です。内部に複数のツールウィンドウを保持します。

記憶対象情報

  • コンポーネントウィンドウの数と階層構造
  • ウィンドウ位置・サイズ
  • ツールバーの表示状態
  • タブの順序・選択状態
  • サブパネル上のツールウィンドウ配置

シリアライズ処理

基本フロー

void LayoutManager::serializeLayout()
{
  QFile file("layout.dat");
  if (file.open(QIODevice::WriteOnly)) {
    QDataStream stream(&file);
    
    // ウィンドウ数保存
    stream << m_windows.size();
    
    // 各ウィンドウ情報保存
    for (auto* window : m_windows) {
      window->saveState(stream);
      stream << "WINDOW_END";
    }
  }
}

タブ情報保存

void TabContainer::saveState(QDataStream &stream)
{
  stream << m_tabs.size(); // タブ数
  
  // タブ情報保存
  for (int i = 0; i < m_tabs.size(); ++i) {
    stream << m_tabs[i].title();
    if (m_tabs[i].isActive()) {
      stream << i; // 選択インデックス
    }
  }
}

ツールウィンドウ保存

void ToolWidget::saveState(QDataStream &stream)
{
  stream << m_title;
  stream << m_position;
  stream << m_size;
  stream << static_cast<int>(m_type);
}

デシリアライズ処理

基本フロー

void LayoutManager::deserializeLayout()
{
  QFile file("layout.dat");
  if (file.open(QIODevice::ReadOnly)) {
    QDataStream stream(&file);
    
    int windowCount;
    stream >> windowCount;
    
    for (int i = 0; i < windowCount; ++i) {
      auto* window = createWindow();
      window->restoreState(stream);
      
      QString marker;
      stream >> marker;
      Q_ASSERT(marker == "WINDOW_END");
    }
  }
}

タブ情報復元

void TabContainer::restoreState(QDataStream &stream)
{
  int tabCount;
  stream >> tabCount;
  
  for (int i = 0; i < tabCount; ++i) {
    QString title;
    stream >> title;
    addTab(title);
  }
  
  int activeIndex;
  stream >> activeIndex;
  setActiveTab(activeIndex);
}

ツールウィンドウ復元

void ToolWidget::restoreState(QDataStream &stream)
{
  stream >> m_title;
  stream >> m_position;
  stream >> m_size;
  
  int typeValue;
  stream >> typeValue;
  m_type = static_cast<ToolType>(typeValue);
  
  // 位置・サイズ適用
  move(m_position);
  resize(m_size);
}

実装上の注意点

  • シリアライズ/デシリアライズ順序の一貫性保持
  • データ境界マーカーの活用
  • 型安全なenumの取り扱い
  • エラー処理の適切な実装

タグ: Qt C++ シリアライズ デシリアライズ UIデザイン

5月25日 03:45 投稿