События рисования не запускаются в развернутом приложении Qt5.Linux

Ответить Пред. темаСлед. тема
Anonymous
 События рисования не запускаются в развернутом приложении Qt5.

Сообщение Anonymous »

У меня есть две Ubuntu 22.04, работающие на виртуальной машине. На первой виртуальной машине установлен Qt5, и я собираю проект Qt5 с помощью CMake. Я могу запустить исполняемый файл, и до сих пор все в порядке.
Я также подготовил сценарий оболочки, который автоматически копирует все необходимые библиотеки и плагины в папки рядом с исполняемым файлом. Затем у меня есть сценарий-оболочка, который связывает эти библиотеки и плагины, а затем запускает исполняемый файл. Затем перехожу на «готовую» Ubuntu 22.04 на другой виртуальной машине, чтобы не был установлен Qt или что-то еще.
Здесь я сталкиваюсь с проблемой: всякий раз, когда я меняю пользовательский интерфейс, например используя полосу прокрутки или устанавливая для растрового изображения QLabel, приложение не обновляет пользовательский интерфейс должным образом. Например, при использовании полосы прокрутки происходит размытие пользовательского интерфейса. Мне приходится перетаскивать край окна и увеличивать/уменьшать его размер, чтобы вызвать событие рисования, и тогда все выглядит нормально.
Кажется, что чего-то не хватает, например плагин или библиотека. Но я понятия не имею, с чего начать поиск.
Вот сценарий оболочки, который ищет библиотеки и плагины на основе исполняемого файла, переданного в качестве входного аргумента. Поскольку сценарий оболочки также пишет сценарий-оболочку, вы найдете его в разделе «Создать сценарий-оболочку» в конце сценария:

Код: Выделить всё

#!/bin/bash

QT_PLUGIN_PATH="/usr/lib/x86_64-linux-gnu/qt5/plugins"

# Check if QT_PLUGIN_PATH exists
if [ ! -d "$QT_PLUGIN_PATH" ]; then
echo "Error: QT_PLUGIN_PATH ($QT_PLUGIN_PATH) does not exist."
exit 1
fi

# Check if an executable is provided
if [ -z "$1" ]; then
echo "Usage: $0 "
exit 1
fi

#     ##########################################################################
echo ">>>>>>"
#     ##########################################################################
# Set variables
EXECUTABLE="$1"
LIB_DEST_DIR="./libs"

# Create destination directory if it doesnt exist
mkdir -p "$LIB_DEST_DIR"

# Use ldd to list the libraries and copy them to the destination directory
ldd "$EXECUTABLE" | grep "=> /" | awk '{print $3}' | while read lib; do
# Extract the filename from the full path
filename=$(basename "$lib")
# Copy the library to the destination directory
echo "Copying $lib to $LIB_DEST_DIR/$filename"
cp "$lib" "$LIB_DEST_DIR/$filename"
done

echo "Libraries copied successfully."

#     ##########################################################################
echo ">>>>>>"
#     ##########################################################################
# Variables
BASE_DIR=$(dirname "$EXECUTABLE")  # The directory where the executable is located
PLUGIN_DEST_DIR="$BASE_DIR/plugins"     # Plugins directory next to the executable
LOG_FILE="temp_qt_plugin_log.txt"

# Create the "plugins" directory if it doesn't exist
mkdir -p "$PLUGIN_DEST_DIR"

# Enable QT_DEBUG_PLUGINS and run the executable to log the plugin search process
export QT_DEBUG_PLUGINS=1
echo "Running the executable to identify required Qt plugins..."
./"$EXECUTABLE" &> "$LOG_FILE"

echo "Logging plugin search process to $LOG_FILE"

# Extract plugin loading info from log
echo "Identifying required plugins and copying them to $PLUGIN_DEST_DIR..."

# Define a function to copy the plugin to the "plugins" directory
copy_plugin() {
local plugin_path="$1"
local plugin_rel_path="${plugin_path#$QT_PLUGIN_PATH/}"  # Strip the QT_PLUGIN_PATH prefix
local dest_path="$PLUGIN_DEST_DIR/$plugin_rel_path"

# Create the destination directory if it doesn't exist
mkdir -p "$(dirname "$dest_path")"

# Copy the plugin
if [[ -f "$plugin_path" ]]; then
cp "$plugin_path" "$dest_path"
echo "Plugin found by $2.  Copied: $plugin_path to $dest_path"
else
echo "Missing: $plugin_path"
fi
}

# Parse the log to find plugins and copy them
grep -E "loaded library" "$LOG_FILE" | while read -r line; do
# Extract the plugin path from the log line
plugin_path=$(echo "$line" | awk -F '"' '{print $2}')

if [[ -f "$plugin_path" ]]; then
# Copy the plugin to the plugins directory
copy_plugin "$plugin_path" "QT_DEBUG_PLUGINS"
else
echo "Plugin not found: $plugin_path"
fi
done

# using strace to capture the system calls related to loading plugins
echo "Running strace to identify plugin-related system calls..."
strace -e trace=open,openat ./"$EXECUTABLE" 2>&1 | grep -E '(platforms|imageformats|plugins).*\.so"$' | while read -r line; do
file_path=$(echo "$line" | awk -F '"' '{print $2}')

if [[ -f "$file_path" ]]; then
# Copy the plugin to the plugins directory if found via strace
copy_plugin "$file_path" "strace"
else
echo "Missing plugin via strace: $file_path, line: $line"
fi
done

# Clean up
echo "Plugin identification and copying complete."

#     ##########################################################################
echo ">>>>>>"
#     ##########################################################################

copy_libraries_for_plugin() {
local plugin="$1"

plugin=$(realpath "$plugin")
if [ -f "$plugin" ]; then
echo "Checking dependencies for plugin: $plugin"

ldd "$plugin" | grep "=> /" | awk '{print $3}' | while read -r lib; do
lib=$(realpath "$lib")

if [ -f "$lib" ] && [ ! -f "$LIB_DEST_DIR/$(basename "$lib")" ]; then
echo "Copying library: $lib to $LIB_DEST_DIR"
cp "$lib" "$LIB_DEST_DIR" 2>/dev/null || echo "Failed to copy library: $lib"
fi
done
fi
}

find "$PLUGIN_DEST_DIR" -type f -name "*.so*" | while read -r plugin; do
copy_libraries_for_plugin "$plugin"
done
echo "> Library copying complete."

#     ##########################################################################
echo ">>>>>>"
#     ##########################################################################
cd "$LIB_DEST_DIR" || { echo "Directory $LIB_DEST_DIR not found."; exit 1; }

# Loop over each file with the ".so.X.Y" pattern
for lib in *.so.*.*; do
# Skip files that have a patch version (e.g., libX.so.5.15.2)
if [[ "$lib" =~ \.so\.[0-9]+\.[0-9]+\.[0-9]+ ]]; then
continue
fi
# Extract the major, minor, and patch version numbers
major_version=$(echo "$lib" | sed -n 's/.*\.so\.\([0-9]*\)\.[0-9]*/\1/p')
minor_version=$(echo "$lib" | sed -n 's/.*\.so\.[0-9]*\.\([0-9]*\)/\1/p')

# Generate the base name for the major version
base_name_major="lib$(echo "$lib" | sed 's/\(.*\.so\)\.[0-9]*\.[0-9]*/\1.'"$major_version"'/')"
# Create a symbolic link from libX.so.major to libX.so.major.minor
if [ -f "$base_name_major" ]; then
rm "$base_name_major"
fi
if [ ! -L "$base_name_major" ]; then
echo "Creating symlink: $base_name_major -> $lib"
ln -s "$lib" "$base_name_major"
else
echo "Symlink $base_name_major already exists"
fi
done

# Loop over each file with the ".so.X.Y.Z" pattern
for lib in *.so.*.*.*; do
# Extract the major, minor, and patch version numbers
major_version=$(echo "$lib" | sed -n 's/.*\.so\.\([0-9]*\)\.[0-9]*\.[0-9]*/\1/p')
minor_version=$(echo "$lib" | sed -n 's/.*\.so\.[0-9]*\.\([0-9]*\)\.[0-9]*/\1/p')
patch_version=$(echo "$lib"  | sed -n 's/.*\.so\.[0-9]*\.[0-9]*\.\([0-9]*\)/\1/p')

# Generate the base names for each level
base_name_major="$(echo "$lib" | sed 's/\(.*\.so\)\.[0-9]*\.[0-9]*\.[0-9]*/\1.'"$major_version"'/')"
base_name_major_minor="$(echo "$lib" | sed 's/\(.*\.so\)\.[0-9]*\.[0-9]*\.[0-9]*/\1.'"$major_version.$minor_version"'/')"

# Create a symbolic link from libX.so.major.minor to libX.so.major.minor.patch
if [ -f "$base_name_major_minor" ]; then
rm "$base_name_major_minor"
fi
if [ ! -L "$base_name_major_minor" ]; then
echo "Creating symlink: $base_name_major_minor -> $lib"
ln -s "$lib" "$base_name_major_minor"
else
echo "Symlink $base_name_major_minor already exists"
fi

# Create a symbolic link from libX.so.major to libX.so.major.minor
if [ -f "$base_name_major" ]; then
rm "$base_name_major"
fi
if [ ! -L "$base_name_major" ]; then
echo "Creating symlink: $base_name_major -> $base_name_major_minor"
ln -s "$base_name_major_minor" "$base_name_major"
else
echo "Symlink $base_name_major already exists"
fi
done
echo "> Symbolic link creation complete."

cd ..
echo "Clean up..."
echo "... delete $EXECUTABLE log files."
rm -r ./Log/
echo "... unset debug environment variable QT_DEBUG_PLUGINS."
unset QT_DEBUG_PLUGINS
echo "... delete temporary files."
rm $LOG_FILE

echo "Clean up done."

#     ##########################################################################
echo ">>>>>>"
#     ##########################################################################
cat  run"$EXECUTABLE".sh
#!/bin/bash

EXECUTABLE=TestExec

# Variables
LIB_DIR="./libs"      # Directory where libraries are located
PLUGIN_DIR="./plugins" # Directory where plugins are located

# Check if the executable exists
if [ ! -x "$EXECUTABLE" ]; then
echo "Error: Executable ($EXECUTABLE) does not exist or is not executable."
exit 1
fi

# Set LD_LIBRARY_PATH to include the directory with the libraries, but preload the system's libstdc++
export LD_LIBRARY_PATH="$LIB_DIR:$LD_LIBRARY_PATH"

# Preload system libstdc++
export LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libstdc++.so.6:/usr/lib/x86_64-linux-gnu/libc.so.6"

# Set QT_PLUGIN_PATH and QT_QPA_PLATFORM_PLUGIN_PATH to include the directories with Qt plugins
export QT_PLUGIN_PATH="$PLUGIN_DIR:$QT_PLUGIN_PATH"
export XDG_SESSION_TYPE="xcb"
export QT_QPA_PLATFORM="xcb"
# Run the executable
echo "Running $EXECUTABLE..."
exec ./"$EXECUTABLE"
EOF

chmod +x run"$EXECUTABLE".sh

echo "> Creating wrapper script done."

#     ##########################################################################
echo ">>>>>>"
#     ##########################################################################
echo "Compressing to $EXECUTABLE.tar.gz ..."
tar -czf "$EXECUTABLE.tar.gz" *
echo "> Compressing completed."
Я провел тест: приложение должно установить растровое изображение в QLabel в зависимости от состояния соединения между приложением и другим устройством.
Прямо сейчас он не обновил пользовательский интерфейс должным образом. Если я изменю размер окна, оно покажет новое состояние соединения. Затем я принудительно перерисовал после изменения состояния соединения в коде, и теперь все работает нормально. Значит, чего-то не хватает, что распознает и выполняет события перерисовки.
Где запускаются эти события?
Примечание: в системе сборки все работает нормально.

Подробнее здесь: https://stackoverflow.com/questions/790 ... ed-qt5-app
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Linux»