System.Text.Encoding 学习笔记

本文通过创建一个名为EncodingTest的类,详细展示了Unicode、ASCII、BigEndianUnicode、Default(ANSI)、GB2312、UTF32、UTF7和UTF8等各种编码方式对字节数组进行转换的过程,包括转换前后字符串长度和字节表示的差异。通过这些实例,读者可以更深入地理解各种编码的区别和应用场景。
部署运行你感兴趣的模型镜像

using System;
using System.Text;

/// <summary>
///  测试各种编码转换前后结果
/// </summary>
public class EncodingTest
{
    [STAThread]
    static void Main()
    {
        EncodingTest test;
        test = new EncodingTest();
    }
   
    public byte[] m_bytes=new byte[256];

    public StringBuilder sb = new StringBuilder(1024);

 public EncodingTest()
 {
        for(int i=0;i<256;i++)
        {
            m_bytes[i]=(byte)i;
        }

        sb.Remove(0, sb.Length);
        sb.Append(System.Text.Encoding.Unicode.GetString(m_bytes));
        Console.WriteLine("Unicode" + sb.Length.ToString());
        Console.WriteLine(BitConverter.ToString(System.Text.Encoding.Unicode.GetBytes(sb.ToString())));

        sb.Remove(0, sb.Length);
        sb.Append(System.Text.Encoding.ASCII.GetString(m_bytes));
        Console.WriteLine("ASCII" + sb.Length.ToString());
        Console.WriteLine(BitConverter.ToString(System.Text.Encoding.ASCII.GetBytes(sb.ToString())));

        sb.Remove(0, sb.Length);
        sb.Append(System.Text.Encoding.BigEndianUnicode.GetString(m_bytes));
        Console.WriteLine("BigEndianUnicode" + sb.Length.ToString());
        Console.WriteLine(BitConverter.ToString(System.Text.Encoding.BigEndianUnicode.GetBytes(sb.ToString())));

        sb.Remove(0, sb.Length);
        sb.Append(System.Text.Encoding.Default.GetString(m_bytes));
        Console.WriteLine("Default" + sb.Length.ToString());
        Console.WriteLine(BitConverter.ToString(System.Text.Encoding.Default.GetBytes(sb.ToString())));

        sb.Remove(0, sb.Length);
        sb.Append(System.Text.Encoding.GetEncoding("GB2312").GetString(m_bytes));
        Console.WriteLine("GB2312" + sb.Length.ToString());
        Console.WriteLine(BitConverter.ToString(System.Text.Encoding.GetEncoding("GB2312").GetBytes(sb.ToString())));

        sb.Remove(0, sb.Length);
        sb.Append(System.Text.Encoding.UTF32.GetString(m_bytes));
        Console.WriteLine("UTF32" + sb.Length.ToString());
        Console.WriteLine(BitConverter.ToString(System.Text.Encoding.UTF32.GetBytes(sb.ToString())));

        sb.Remove(0, sb.Length);
        sb.Append(System.Text.Encoding.UTF7.GetString(m_bytes));
        Console.WriteLine("UTF7" + sb.Length.ToString());
        Console.WriteLine(BitConverter.ToString(System.Text.Encoding.UTF7.GetBytes(sb.ToString())));

        sb.Remove(0, sb.Length);
        sb.Append(System.Text.Encoding.UTF8.GetString(m_bytes));
        Console.WriteLine("UTF8" + sb.Length.ToString());
        Console.WriteLine(BitConverter.ToString(System.Text.Encoding.UTF8.GetBytes(sb.ToString())));
 }
}

结果

Unicode126
00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-14-15-16-17-18-19-1A-1B-1C-1D-1E-1F-20-21-22-23-24-25-26-27-28-29-2A-2B-2C-2D-2E-2F-30-31-32-33-34-35-36-37-38-39-3A-3B-3C-3D-3E-3F-40-41-42-43-44-45-46-47-48-49-4A-4B-4C-4D-4E-4F-50-51-52-53-54-55-56-57-58-59-5A-5B-5C-5D-5E-5F-60-61-62-63-64-65-66-67-68-69-6A-6B-6C-6D-6E-6F-70-71-72-73-74-75-76-77-78-79-7A-7B-7C-7D-7E-7F-80-81-82-83-84-85-86-87-88-89-8A-8B-8C-8D-8E-8F-90-91-92-93-94-95-96-97-98-99-9A-9B-9C-9D-9E-9F-A0-A1-A2-A3-A4-A5-A6-A7-A8-A9-AA-AB-AC-AD-AE-AF-B0-B1-B2-B3-B4-B5-B6-B7-B8-B9-BA-BB-BC-BD-BE-BF-C0-C1-C2-C3-C4-C5-C6-C7-C8-C9-CA-CB-CC-CD-CE-CF-D0-D1-D2-D3-D4-D5-D6-D7-DA-DB-DC-DD-E0-E1-E2-E3-E4-E5-E6-E7-E8-E9-EA-EB-EC-ED-EE-EF-F0-F1-F2-F3-F4-F5-F6-F7-F8-F9-FA-FB-FC-FD-FE-FF
ASCII256
00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-14-15-16-17-18-19-1A-1B-1C-1D-1E-1F-20-21-22-23-24-25-26-27-28-29-2A-2B-2C-2D-2E-2F-30-31-32-33-34-35-36-37-38-39-3A-3B-3C-3D-3E-3F-40-41-42-43-44-45-46-47-48-49-4A-4B-4C-4D-4E-4F-50-51-52-53-54-55-56-57-58-59-5A-5B-5C-5D-5E-5F-60-61-62-63-64-65-66-67-68-69-6A-6B-6C-6D-6E-6F-70-71-72-73-74-75-76-77-78-79-7A-7B-7C-7D-7E-7F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F-3F
BigEndianUnicode126
00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-14-15-16-17-18-19-1A-1B-1C-1D-1E-1F-20-21-22-23-24-25-26-27-28-29-2A-2B-2C-2D-2E-2F-30-31-32-33-34-35-36-37-38-39-3A-3B-3C-3D-3E-3F-40-41-42-43-44-45-46-47-48-49-4A-4B-4C-4D-4E-4F-50-51-52-53-54-55-56-57-58-59-5A-5B-5C-5D-5E-5F-60-61-62-63-64-65-66-67-68-69-6A-6B-6C-6D-6E-6F-70-71-72-73-74-75-76-77-78-79-7A-7B-7C-7D-7E-7F-80-81-82-83-84-85-86-87-88-89-8A-8B-8C-8D-8E-8F-90-91-92-93-94-95-96-97-98-99-9A-9B-9C-9D-9E-9F-A0-A1-A2-A3-A4-A5-A6-A7-A8-A9-AA-AB-AC-AD-AE-AF-B0-B1-B2-B3-B4-B5-B6-B7-B8-B9-BA-BB-BC-BD-BE-BF-C0-C1-C2-C3-C4-C5-C6-C7-C8-C9-CA-CB-CC-CD-CE-CF-D0-D1-D2-D3-D4-D5-D6-D7-DA-DB-DC-DD-E0-E1-E2-E3-E4-E5-E6-E7-E8-E9-EA-EB-EC-ED-EE-EF-F0-F1-F2-F3-F4-F5-F6-F7-F8-F9-FA-FB-FC-FD-FE-FF
Default193
00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-14-15-16-17-18-19-1A-1B-1C-1D-1E-1F-20-21-22-23-24-25-26-27-28-29-2A-2B-2C-2D-2E-2F-30-31-32-33-34-35-36-37-38-39-3A-3B-3C-3D-3E-3F-40-41-42-43-44-45-46-47-48-49-4A-4B-4C-4D-4E-4F-50-51-52-53-54-55-56-57-58-59-5A-5B-5C-5D-5E-5F-60-61-62-63-64-65-66-67-68-69-6A-6B-6C-6D-6E-6F-70-71-72-73-74-75-76-77-78-79-7A-7B-7C-7D-7E-7F-80-81-82-83-84-85-86-87-88-89-8A-8B-8C-8D-8E-8F-90-91-92-93-94-95-96-97-98-99-9A-9B-9C-9D-9E-9F-A0-A1-A2-A3-A4-A5-A6-A7-A8-A9-AA-AB-AC-AD-AE-AF-B0-B1-B2-B3-B4-B5-B6-B7-B8-B9-BA-BB-BC-BD-BE-BF-C0-C1-C2-C3-C4-C5-C6-C7-C8-C9-CA-CB-CC-CD-CE-CF-D0-D1-D2-D3-D4-D5-D6-D7-D8-D9-DA-DB-DC-DD-DE-DF-E0-E1-E2-E3-E4-E5-E6-E7-E8-E9-EA-EB-EC-ED-EE-EF-F0-F1-F2-F3-F4-F5-F6-F7-F8-F9-FA-FB-FC-FD-FE-FF

GB2312193
00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-14-15-16-17-18-19-1A-1B-1C-1D-1E-1F-20-21-22-23-24-25-26-27-28-29-2A-2B-2C-2D-2E-2F-30-31-32-33-34-35-36-37-38-39-3A-3B-3C-3D-3E-3F-40-41-42-43-44-45-46-47-48-49-4A-4B-4C-4D-4E-4F-50-51-52-53-54-55-56-57-58-59-5A-5B-5C-5D-5E-5F-60-61-62-63-64-65-66-67-68-69-6A-6B-6C-6D-6E-6F-70-71-72-73-74-75-76-77-78-79-7A-7B-7C-7D-7E-7F-80-81-82-83-84-85-86-87-88-89-8A-8B-8C-8D-8E-8F-90-91-92-93-94-95-96-97-98-99-9A-9B-9C-9D-9E-9F-A0-A1-A2-A3-A4-A5-A6-A7-A8-A9-AA-AB-AC-AD-AE-AF-B0-B1-B2-B3-B4-B5-B6-B7-B8-B9-BA-BB-BC-BD-BE-BF-C0-C1-C2-C3-C4-C5-C6-C7-C8-C9-CA-CB-CC-CD-CE-CF-D0-D1-D2-D3-D4-D5-D6-D7-D8-D9-DA-DB-DC-DD-DE-DF-E0-E1-E2-E3-E4-E5-E6-E7-E8-E9-EA-EB-EC-ED-EE-EF-F0-F1-F2-F3-F4-F5-F6-F7-F8-F9-FA-FB-FC-FD-FE-FF
UTF320

UTF7255
2B-41-41-41-41-41-51-41-43-41-41-4D-41-42-41-41-46-41-41-59-41-42-77-41-49-2D-09-0A-2B-41-41-73-41-44-41-2D-0D-2B-41-41-34-41-44-77-41-51-41-42-45-41-45-67-41-54-41-42-51-41-46-51-41-57-41-42-63-41-47-41-41-5A-41-42-6F-41-47-77-41-63-41-42-30-41-48-67-41-66-2D-20-2B-41-43-45-41-49-67-41-6A-41-43-51-41-4A-51-41-6D-2D-27-28-29-2B-41-43-6F-2D-2C-2D-2E-2F-30-31-32-33-34-35-36-37-38-39-3A-2B-41-44-73-41-50-41-41-39-41-44-34-2D-3F-2B-41-45-41-2D-41-42-43-44-45-46-47-48-49-4A-4B-4C-4D-4E-4F-50-51-52-53-54-55-56-57-58-59-5A-2B-41-46-73-41-58-41-42-64-41-46-34-41-58-77-42-67-2D-61-62-63-64-65-66-67-68-69-6A-6B-6C-6D-6E-6F-70-71-72-73-74-75-76-77-78-79-7A-2B-41-48-73-41-66-41-42-39-41-48-34-41-66-77-43-41-41-49-45-41-67-67-43-44-41-49-51-41-68-51-43-47-41-49-63-41-69-41-43-4A-41-49-6F-41-69-77-43-4D-41-49-30-41-6A-67-43-50-41-4A-41-41-6B-51-43-53-41-4A-4D-41-6C-41-43-56-41-4A-59-41-6C-77-43-59-41-4A-6B-41-6D-67-43-62-41-4A-77-41-6E-51-43-65-41-4A-38-41-6F-41-43-68-41-4B-49-41-6F-77-43-6B-41-4B-55-41-70-67-43-6E-41-4B-67-41-71-51-43-71-41-4B-73-41-72-41-43-74-41-4B-34-41-72-77-43-77-41-4C-45-41-73-67-43-7A-41-4C-51-41-74-51-43-32-41-4C-63-41-75-41-43-35-41-4C-6F-41-75-77-43-38-41-4C-30-41-76-67-43-2F-41-4D-41-41-77-51-44-43-41-4D-4D-41-78-41-44-46-41-4D-59-41-78-77-44-49-41-4D-6B-41-79-67-44-4C-41-4D-77-41-7A-51-44-4F-41-4D-38-41-30-41-44-52-41-4E-49-41-30-77-44-55-41-4E-55-41-31-67-44-58-41-4E-67-41-32-51-44-61-41-4E-73-41-33-41-44-64-41-4E-34-41-33-77-44-67-41-4F-45-41-34-67-44-6A-41-4F-51-41-35-51-44-6D-41-4F-63-41-36-41-44-70-41-4F-6F-41-36-77-44-73-41-4F-30-41-37-67-44-76-41-50-41-41-38-51-44-79-41-50-4D-41-39-41-44-31-41-50-59-41-39-77-44-34-41-50-6B-41-2B-67-44-37-41-50-77-41-2F-51-44-2B-41-50-38-2D
UTF8128
00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-14-15-16-17-18-19-1A-1B-1C-1D-1E-1F-20-21-22-23-24-25-26-27-28-29-2A-2B-2C-2D-2E-2F-30-31-32-33-34-35-36-37-38-39-3A-3B-3C-3D-3E-3F-40-41-42-43-44-45-46-47-48-49-4A-4B-4C-4D-4E-4F-50-51-52-53-54-55-56-57-58-59-5A-5B-5C-5D-5E-5F-60-61-62-63-64-65-66-67-68-69-6A-6B-6C-6D-6E-6F-70-71-72-73-74-75-76-77-78-79-7A-7B-7C-7D-7E-7F

注意:1、sb的长度并不一定和byte长度相等

 

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

这是完整代码:import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_squared_error, r2_score from sklearn.preprocessing import StandardScaler import joblib import tkinter as tk from tkinter import ttk, messagebox, filedialog from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg import warnings from datetime import datetime import os warnings.filterwarnings('ignore') class WaterPlantModel: """单个水厂的模型和数据""" def __init__(self, plant_name): self.plant_name = plant_name self.model_dosage_1 = None self.model_dosage_2 = None self.model_water_quality = None self.scaler_dosage = None self.scaler_water_quality = None self.data = None self.feedback_data = [] def load_data(self, filepath): """加载数据""" self.data = pd.read_csv(filepath) print(f"{self.plant_name}水厂数据加载成功,共{len(self.data)}条记录") def preprocess_data(self): """数据预处理""" if self.data is None: raise ValueError("请先加载数据") # 创建滞后特征(4小时后的出水浊度) self.data['future_turbidity'] = self.data['出水浊度'].shift(-1) self.data = self.data.dropna() # 分离特征和目标变量 # 需矾量模型的特征 features_dosage = [ '原水浊度', '原水ph', '1#沉淀池流量', '2#沉淀池流量', '矾原液密度', '矾液浓度' ] # 水质模型的特征 features_water_quality = features_dosage + ['1#需矾量', '2#需矾量'] # 目标变量 target_dosage_1 = '1#需矾量' target_dosage_2 = '2#需矾量' target_water_quality = 'future_turbidity' return features_dosage, features_water_quality, target_dosage_1, target_dosage_2, target_water_quality def train_models(self): """训练模型""" if self.data is None: raise ValueError("请先加载数据") features_dosage, features_water_quality, target_dosage_1, target_dosage_2, target_water_quality = self.preprocess_data() # 训练需矾量模型1 X_dosage_1 = self.data[features_dosage] y_dosage_1 = self.data[target_dosage_1] X_train, X_test, y_train, y_test = train_test_split( X_dosage_1, y_dosage_1, test_size=0.2, random_state=42 ) self.scaler_dosage = StandardScaler() X_train_scaled = self.scaler_dosage.fit_transform(X_train) X_test_scaled = self.scaler_dosage.transform(X_test) self.model_dosage_1 = RandomForestRegressor(n_estimators=100, random_state=42) self.model_dosage_1.fit(X_train_scaled, y_train) y_pred = self.model_dosage_1.predict(X_test_scaled) mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print(f"{self.plant_name}水厂1#需矾量模型 - MSE: {mse:.4f}, R²: {r2:.4f}") # 训练需矾量模型2 y_dosage_2 = self.data[target_dosage_2] X_train, X_test, y_train, y_test = train_test_split( X_dosage_1, y_dosage_2, test_size=0.2, random_state=42 ) X_train_scaled = self.scaler_dosage.transform(X_train) X_test_scaled = self.scaler_dosage.transform(X_test) self.model_dosage_2 = RandomForestRegressor(n_estimators=100, random_state=42) self.model_dosage_2.fit(X_train_scaled, y_train) y_pred = self.model_dosage_2.predict(X_test_scaled) mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print(f"{self.plant_name}水厂2#需矾量模型 - MSE: {mse:.4f}, R²: {r2:.4f}") # 训练水质模型 X_water_quality = self.data[features_water_quality] y_water_quality = self.data[target_water_quality] X_train, X_test, y_train, y_test = train_test_split( X_water_quality, y_water_quality, test_size=0.2, random_state=42 ) self.scaler_water_quality = StandardScaler() X_train_scaled = self.scaler_water_quality.fit_transform(X_train) X_test_scaled = self.scaler_water_quality.transform(X_test) self.model_water_quality = RandomForestRegressor(n_estimators=100, random_state=42) self.model_water_quality.fit(X_train_scaled, y_train) y_pred = self.model_water_quality.predict(X_test_scaled) mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print(f"{self.plant_name}水厂水质模型 - MSE: {mse:.4f}, R²: {r2:.4f}") def save_models(self, path_prefix=None): """保存模型""" if path_prefix is None: path_prefix = self.plant_name joblib.dump(self.model_dosage_1, f"{path_prefix}_dosage_1.pkl") joblib.dump(self.model_dosage_2, f"{path_prefix}_dosage_2.pkl") joblib.dump(self.model_water_quality, f"{path_prefix}_water_quality.pkl") joblib.dump(self.scaler_dosage, f"{path_prefix}_scaler_dosage.pkl") joblib.dump(self.scaler_water_quality, f"{path_prefix}_scaler_water_quality.pkl") print(f"{self.plant_name}水厂模型保存成功") def load_models(self, path_prefix=None): """加载模型""" if path_prefix is None: path_prefix = self.plant_name self.model_dosage_1 = joblib.load(f"{path_prefix}_dosage_1.pkl") self.model_dosage_2 = joblib.load(f"{path_prefix}_dosage_2.pkl") self.model_water_quality = joblib.load(f"{path_prefix}_water_quality.pkl") self.scaler_dosage = joblib.load(f"{path_prefix}_scaler_dosage.pkl") self.scaler_water_quality = joblib.load(f"{path_prefix}_scaler_water_quality.pkl") print(f"{self.plant_name}水厂模型加载成功") def predict_dosage_1(self, input_data): """预测1#需矾量""" input_scaled = self.scaler_dosage.transform([input_data]) return self.model_dosage_1.predict(input_scaled)[0] def predict_dosage_2(self, input_data): """预测2#需矾量""" input_scaled = self.scaler_dosage.transform([input_data]) return self.model_dosage_2.predict(input_scaled)[0] def predict_water_quality(self, input_data): """预测出水浊度""" input_scaled = self.scaler_water_quality.transform([input_data]) return self.model_water_quality.predict(input_scaled)[0] def add_feedback(self, input_data, actual_turbidity, predicted_turbidity): """添加反馈数据""" similarity = 1 - (abs(actual_turbidity - predicted_turbidity) / max(actual_turbidity, predicted_turbidity)) timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.feedback_data.append({ 'timestamp': timestamp, 'input': input_data, 'actual_turbidity': actual_turbidity, 'predicted_turbidity': predicted_turbidity, 'similarity': similarity }) return similarity def export_feedback_data(self, filename=None): """导出反馈数据为CSV文件,格式与原始数据表一致""" if not self.feedback_data: messagebox.showwarning("警告", "没有反馈数据可导出") return False if filename is None: filename = filedialog.asksaveasfilename( defaultextension=".csv", filetypes=[("CSV files", "*.csv"), ("All files", "*.*")], title=f"保存{self.plant_name}水厂反馈数据" ) if not filename: return False # 创建与原始数据表结构一致的DataFrame feedback_list = [] for fd in self.feedback_data: # 将反馈数据转换为与原始数据表相同的格式 feedback_row = { '时间': fd['timestamp'], '原水浊度': fd['input'][0], '原水ph': fd['input'][1], '1#沉淀池流量': fd['input'][2], '2#沉淀池流量': fd['input'][3], '矾原液密度': fd['input'][4], '矾液浓度': fd['input'][5], '1#需矾量': fd['input'][6], '2#需矾量': fd['input'][7], '出水浊度': fd['actual_turbidity'], # 以下字段在反馈数据中没有,设置为空或默认值 '1#矾液流量': None, '2#矾液流量': None, '1#沉后ph': None, '1#沉后浊度': None, '2#沉后ph': None, '2#沉后浊度': None, '滤后ph': None, '滤后浊度': None, '出水ph': None } feedback_list.append(feedback_row) # 创建DataFrame并确保列的顺序与原始数据一致 original_columns = [ '时间', '原水浊度', '原水ph', '1#沉淀池流量', '1#矾液流量', '2#沉淀池流量', '2#矾液流量', '矾原液密度', '矾液浓度', '1#需矾量', '2#需矾量', '1#沉后ph', '1#沉后浊度', '2#沉后ph', '2#沉后浊度', '滤后ph', '滤后浊度', '出水ph', '出水浊度' ] feedback_df = pd.DataFrame(feedback_list) # 确保所有原始列都存在,如果不存在则添加空列 for col in original_columns: if col not in feedback_df.columns: feedback_df[col] = None # 按原始顺序重新排列列 feedback_df = feedback_df[original_columns] # 保存到CSV文件 feedback_df.to_csv(filename, index=False, encoding='utf-8-sig') print(f"{self.plant_name}水厂反馈数据已导出到: {filename}") return True def retrain_with_feedback(self): """使用反馈数据重新训练模型""" if not self.feedback_data: print("没有反馈数据可用于重新训练") return # 将反馈数据转换为DataFrame feedback_df = pd.DataFrame([{ '原水浊度': fd['input'][0], '原水ph': fd['input'][1], '1#沉淀池流量': fd['input'][2], '2#沉淀池流量': fd['input'][3], '矾原液密度': fd['input'][4], '矾液浓度': fd['input'][5], '1#需矾量': fd['input'][6], '2#需矾量': fd['input'][7], 'future_turbidity': fd['actual_turbidity'] } for fd in self.feedback_data]) # 合并原始数据和反馈数据 combined_data = pd.concat([self.data, feedback_df], ignore_index=True) # 重新训练水质模型 features_water_quality = [ '原水浊度', '原水ph', '1#沉淀池流量', '2#沉淀池流量', '矾原液密度', '矾液浓度', '1#需矾量', '2#需矾量' ] target_water_quality = 'future_turbidity' X = combined_data[features_water_quality] y = combined_data[target_water_quality] X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) self.scaler_water_quality = StandardScaler() X_train_scaled = self.scaler_water_quality.fit_transform(X_train) X_test_scaled = self.scaler_water_quality.transform(X_test) self.model_water_quality = RandomForestRegressor(n_estimators=100, random_state=42) self.model_water_quality.fit(X_train_scaled, y_train) y_pred = self.model_water_quality.predict(X_test_scaled) mse = mean_squared_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print(f"{self.plant_name}水厂重新训练后的水质模型 - MSE: {mse:.4f}, R²: {r2:.4f}") # 清空反馈数据 self.feedback_data = [] print(f"{self.plant_name}水厂模型已使用反馈数据重新训练") class AlumDosagePredictionSystem: """多水厂预测系统""" def __init__(self): self.plants = { "JB": WaterPlantModel("JB"), "GH": WaterPlantModel("GH"), "LG": WaterPlantModel("LG"), "THY": WaterPlantModel("THY") } self.current_plant = "JB" # 默认水厂 def get_current_model(self): """获取当前水厂模型""" return self.plants[self.current_plant] def switch_plant(self, plant_name): """切换当前水厂""" if plant_name in self.plants: self.current_plant = plant_name print(f"已切换到{plant_name}水厂") return True return False class AlumPredictionApp: def __init__(self, root, prediction_system): self.root = root self.root.title("自来水厂矾液投加预测系统") self.root.geometry("1200x800") self.prediction_system = prediction_system # 创建顶部控制框架 self.control_frame = ttk.Frame(root) self.control_frame.pack(fill='x', padx=10, pady=5) # 水厂选择下拉菜单 ttk.Label(self.control_frame, text="选择水厂:").grid(row=0, column=0, padx=5, pady=5, sticky='e') self.plant_var = tk.StringVar(value="JB") self.plant_combo = ttk.Combobox(self.control_frame, textvariable=self.plant_var, values=list(self.prediction_system.plants.keys()), state="readonly", width=10) self.plant_combo.grid(row=0, column=1, padx=5, pady=5) self.plant_combo.bind('<<ComboboxSelected>>', self.on_plant_changed) # 模型操作按钮 ttk.Button(self.control_frame, text="加载模型", command=self.load_models).grid(row=0, column=2, padx=5, pady=5) ttk.Button(self.control_frame, text="训练模型", command=self.train_models).grid(row=0, column=3, padx=5, pady=5) ttk.Button(self.control_frame, text="保存模型", command=self.save_models).grid(row=0, column=4, padx=5, pady=5) # 创建公共参数框架 self.common_frame = ttk.LabelFrame(root, text="公共参数") self.common_frame.pack(fill='x', padx=10, pady=5) # 公共参数输入框 ttk.Label(self.common_frame, text="原水浊度:").grid(row=0, column=0, padx=5, pady=5, sticky='e') self.common_turbidity = ttk.Entry(self.common_frame, width=10) self.common_turbidity.grid(row=0, column=1, padx=5, pady=5) ttk.Label(self.common_frame, text="原水pH:").grid(row=0, column=2, padx=5, pady=5, sticky='e') self.common_ph = ttk.Entry(self.common_frame, width=10) self.common_ph.grid(row=0, column=3, padx=5, pady=5) ttk.Label(self.common_frame, text="矾原液密度:").grid(row=0, column=4, padx=5, pady=5, sticky='e') self.common_density = ttk.Entry(self.common_frame, width=10) self.common_density.grid(row=0, column=5, padx=5, pady=5) ttk.Label(self.common_frame, text="矾液浓度:").grid(row=0, column=6, padx=5, pady=5, sticky='e') self.common_concentration = ttk.Entry(self.common_frame, width=10) self.common_concentration.grid(row=0, column=7, padx=5, pady=5) # 创建选项卡 self.notebook = ttk.Notebook(root) self.notebook.pack(fill='both', expand=True, padx=10, pady=10) # 创建各个选项卡 self.create_dosage_1_tab() self.create_dosage_2_tab() self.create_water_quality_tab() self.create_combined_tab() self.create_feedback_tab() self.create_curve_tab() # 更新水厂标签 self.update_plant_label() def on_plant_changed(self, event): """水厂选择改变事件""" plant_name = self.plant_var.get() if self.prediction_system.switch_plant(plant_name): self.update_plant_label() def update_plant_label(self): """更新界面中的水厂标签""" plant_name = self.prediction_system.current_plant for tab_id in self.notebook.tabs(): tab = self.nametowidget(tab_id) if hasattr(tab, 'winfo_children'): for child in tab.winfo_children(): if isinstance(child, ttk.LabelFrame): child.config(text=f"{child.cget('text').split('(')[0].strip()}({plant_name}水厂)") def load_models(self): """加载当前水厂模型""" try: plant_model = self.prediction_system.get_current_model() plant_model.load_models() messagebox.showinfo("成功", f"{self.prediction_system.current_plant}水厂模型加载成功") except Exception as e: messagebox.showerror("错误", f"加载模型失败: {str(e)}") def train_models(self): """训练当前水厂模型""" try: plant_name = self.prediction_system.current_plant data_file = f"{plant_name}_water_quality_data.csv" if not os.path.exists(data_file): messagebox.showerror("错误", f"找不到数据文件: {data_file}") return plant_model = self.prediction_system.get_current_model() plant_model.load_data(data_file) plant_model.train_models() messagebox.showinfo("成功", f"{plant_name}水厂模型训练成功") except Exception as e: messagebox.showerror("错误", f"训练模型失败: {str(e)}") def save_models(self): """保存当前水厂模型""" try: plant_model = self.prediction_system.get_current_model() plant_model.save_models() messagebox.showinfo("成功", f"{self.prediction_system.current_plant}水厂模型保存成功") except Exception as e: messagebox.showerror("错误", f"保存模型失败: {str(e)}") def create_dosage_1_tab(self): """创建1#需矾量预测选项卡""" tab = ttk.Frame(self.notebook) self.notebook.add(tab, text="1#需矾量预测") frame = ttk.LabelFrame(tab, text="1#需矾量预测(JB水厂)") frame.pack(fill='both', expand=True, padx=10, pady=10) # 创建输入框 ttk.Label(frame, text="1#沉淀池流量:").grid(row=0, column=0, padx=5, pady=5, sticky='e') self.flow_1 = ttk.Entry(frame, width=15) self.flow_1.grid(row=0, column=1, padx=5, pady=5) # 预测按钮 ttk.Button(frame, text="预测1#需矾量", command=self.predict_dosage_1).grid(row=1, column=0, columnspan=2, pady=10) # 结果显示 ttk.Label(frame, text="预测1#需矾量:").grid(row=2, column=0, padx=5, pady=5, sticky='e') self.result_dosage_1 = ttk.Label(frame, text="", width=15) self.result_dosage_1.grid(row=2, column=1, padx=5, pady=5, sticky='w') def create_dosage_2_tab(self): """创建2#需矾量预测选项卡""" tab = ttk.Frame(self.notebook) self.notebook.add(tab, text="2#需矾量预测") frame = ttk.LabelFrame(tab, text="2#需矾量预测(JB水厂)") frame.pack(fill='both', expand=True, padx=10, pady=10) # 创建输入框 ttk.Label(frame, text="2#沉淀池流量:").grid(row=0, column=0, padx=5, pady=5, sticky='e') self.flow_2 = ttk.Entry(frame, width=15) self.flow_2.grid(row=0, column=1, padx=5, pady=5) # 预测按钮 ttk.Button(frame, text="预测2#需矾量", command=self.predict_dosage_2).grid(row=1, column=0, columnspan=2, pady=10) # 结果显示 ttk.Label(frame, text="预测2#需矾量:").grid(row=2, column=0, padx=5, pady=5, sticky='e') self.result_dosage_2 = ttk.Label(frame, text="", width=15) self.result_dosage_2.grid(row=2, column=1, padx=5, pady=5, sticky='w') def create_water_quality_tab(self): """创建水质预测选项卡""" tab = ttk.Frame(self.notebook) self.notebook.add(tab, text="水质预测") frame = ttk.LabelFrame(tab, text="水质预测(JB水厂)") frame.pack(fill='both', expand=True, padx=10, pady=10) # 创建输入框 ttk.Label(frame, text="1#沉淀池流量:").grid(row=0, column=0, padx=5, pady=5, sticky='e') self.flow1_wq = ttk.Entry(frame, width=15) self.flow1_wq.grid(row=0, column=1, padx=5, pady=5) ttk.Label(frame, text="2#沉淀池流量:").grid(row=1, column=0, padx=5, pady=5, sticky='e') self.flow2_wq = ttk.Entry(frame, width=15) self.flow2_wq.grid(row=1, column=1, padx=5, pady=5) ttk.Label(frame, text="1#需矾量:").grid(row=2, column=0, padx=5, pady=5, sticky='e') self.dosage1_wq = ttk.Entry(frame, width=15) self.dosage1_wq.grid(row=2, column=1, padx=5, pady=5) ttk.Label(frame, text="2#需矾量:").grid(row=3, column=0, padx=5, pady=5, sticky='e') self.dosage2_wq = ttk.Entry(frame, width=15) self.dosage2_wq.grid(row=3, column=1, padx=5, pady=5) # 预测按钮 ttk.Button(frame, text="预测出水浊度", command=self.predict_water_quality).grid(row=4, column=0, columnspan=2, pady=10) # 结果显示 ttk.Label(frame, text="预测出水浊度:").grid(row=5, column=0, padx=5, pady=5, sticky='e') self.result_water_quality = ttk.Label(frame, text="", width=15) self.result_water_quality.grid(row=5, column=1, padx=5, pady=5, sticky='w') def create_combined_tab(self): """创建组合预测选项卡""" tab = ttk.Frame(self.notebook) self.notebook.add(tab, text="组合预测") frame = ttk.LabelFrame(tab, text="组合预测(JB水厂)") frame.pack(fill='both', expand=True, padx=10, pady=10) # 创建输入框 ttk.Label(frame, text="1#沉淀池流量:").grid(row=0, column=0, padx=5, pady=5, sticky='e') self.flow1_combined = ttk.Entry(frame, width=15) self.flow1_combined.grid(row=0, column=1, padx=5, pady=5) ttk.Label(frame, text="2#沉淀池流量:").grid(row=1, column=0, padx=5, pady=5, sticky='e') self.flow2_combined = ttk.Entry(frame, width=15) self.flow2_combined.grid(row=1, column=1, padx=5, pady=5) # 预测按钮 ttk.Button(frame, text="预测1#需矾量", command=self.predict_dosage_1_combined).grid(row=2, column=0, pady=10) ttk.Button(frame, text="预测2#需矾量", command=self.predict_dosage_2_combined).grid(row=2, column=1, pady=10) ttk.Button(frame, text="预测出水浊度", command=self.predict_water_quality_combined).grid(row=3, column=0, columnspan=2, pady=10) # 结果显示 ttk.Label(frame, text="预测1#需矾量:").grid(row=4, column=0, padx=5, pady=5, sticky='e') self.result_dosage_1_combined = ttk.Label(frame, text="", width=15) self.result_dosage_1_combined.grid(row=4, column=1, padx=5, pady=5, sticky='w') ttk.Label(frame, text="预测2#需矾量:").grid(row=5, column=0, padx=5, pady=5, sticky='e') self.result_dosage_2_combined = ttk.Label(frame, text="", width=15) self.result_dosage_2_combined.grid(row=5, column=1, padx=5, pady=5, sticky='w') ttk.Label(frame, text="预测出水浊度:").grid(row=6, column=0, padx=5, pady=5, sticky='e') self.result_water_quality_combined = ttk.Label(frame, text="", width=15) self.result_water_quality_combined.grid(row=6, column=1, padx=5, pady=5, sticky='w') def create_feedback_tab(self): """创建反馈选项卡""" tab = ttk.Frame(self.notebook) self.notebook.add(tab, text="反馈系统") frame = ttk.LabelFrame(tab, text="反馈系统(JB水厂)") frame.pack(fill='both', expand=True, padx=10, pady=10) # 实际浊度输入 ttk.Label(frame, text="实际出水浊度:").grid(row=0, column=0, padx=5, pady=5, sticky='e') self.actual_turbidity = ttk.Entry(frame, width=15) self.actual_turbidity.grid(row=0, column=1, padx=5, pady=5) # 预测浊度显示 ttk.Label(frame, text="预测出水浊度:").grid(row=1, column=0, padx=5, pady=5, sticky='e') self.predicted_turbidity_fb = ttk.Label(frame, text="", width=15) self.predicted_turbidity_fb.grid(row=1, column=1, padx=5, pady=5, sticky='w') # 相似度显示 ttk.Label(frame, text="预测相似度:").grid(row=2, column=0, padx=5, pady=5, sticky='e') self.similarity = ttk.Label(frame, text="", width=15) self.similarity.grid(row=2, column=1, padx=5, pady=5, sticky='w') # 按钮 ttk.Button(frame, text="提交反馈", command=self.submit_feedback).grid(row=3, column=0, padx=5, pady=10) ttk.Button(frame, text="重新训练模型", command=self.retrain_model).grid(row=3, column=1, padx=5, pady=10) # 添加导出按钮 ttk.Button(frame, text="导出反馈数据", command=self.export_feedback).grid(row=4, column=0, columnspan=2, pady=10) def create_curve_tab(self): """创建曲线选项卡""" tab = ttk.Frame(self.notebook) self.notebook.add(tab, text="关系曲线") frame = ttk.LabelFrame(tab, text="关系曲线(JB水厂)") frame.pack(fill='both', expand=True, padx=10, pady=10) # 创建画布 self.fig, self.ax = plt.subplots(figsize=(8, 6)) self.canvas = FigureCanvasTkAgg(self.fig, frame) self.canvas.get_tk_widget().pack(fill='both', expand=True) # 更新曲线按钮 ttk.Button(frame, text="更新曲线", command=self.update_curve).pack(pady=10) def get_common_params(self): """获取公共参数""" try: return [ float(self.common_turbidity.get()), float(self.common_ph.get()), float(self.common_density.get()), float(self.common_concentration.get()) ] except: messagebox.showerror("错误", "请先输入公共参数") return None def predict_dosage_1(self): """预测1#需矾量""" common_params = self.get_common_params() if common_params is None: return try: input_data = [ common_params[0], # 原水浊度 common_params[1], # 原水pH float(self.flow_1.get()), 0, # 2#沉淀池流量设为0,因为只预测1# common_params[2], # 矾原液密度 common_params[3] # 矾液浓度 ] plant_model = self.prediction_system.get_current_model() prediction = plant_model.predict_dosage_1(input_data) self.result_dosage_1.config(text=f"{prediction:.4f}") except Exception as e: messagebox.showerror("错误", f"输入数据有误: {str(e)}") def predict_dosage_2(self): """预测2#需矾量""" common_params = self.get_common_params() if common_params is None: return try: input_data = [ common_params[0], # 原水浊度 common_params[1], # 原水pH 0, # 1#沉淀池流量设为0,因为只预测2# float(self.flow_2.get()), common_params[2], # 矾原液密度 common_params[3] # 矾液浓度 ] plant_model = self.prediction_system.get_current_model() prediction = plant_model.predict_dosage_2(input_data) self.result_dosage_2.config(text=f"{prediction:.4f}") except Exception as e: messagebox.showerror("错误", f"输入数据有误: {str(e)}") def predict_water_quality(self): """预测出水浊度""" common_params = self.get_common_params() if common_params is None: return try: input_data = [ common_params[0], # 原水浊度 common_params[1], # 原水pH float(self.flow1_wq.get()), float(self.flow2_wq.get()), common_params[2], # 矾原液密度 common_params[3], # 矾液浓度 float(self.dosage1_wq.get()), float(self.dosage2_wq.get()) ] plant_model = self.prediction_system.get_current_model() prediction = plant_model.predict_water_quality(input_data) self.result_water_quality.config(text=f"{prediction:.4f}") self.predicted_turbidity_fb.config(text=f"{prediction:.4f}") except Exception as e: messagebox.showerror("错误", f"输入数据有误: {str(e)}") def predict_dosage_1_combined(self): """组合预测1#需矾量""" common_params = self.get_common_params() if common_params is None: return try: input_data = [ common_params[0], # 原水浊度 common_params[1], # 原水pH float(self.flow1_combined.get()), 0, # 2#沉淀池流量设为0,因为只预测1# common_params[2], # 矾原液密度 common_params[3] # 矾液浓度 ] plant_model = self.prediction_system.get_current_model() prediction = plant_model.predict_dosage_1(input_data) self.result_dosage_1_combined.config(text=f"{prediction:.4f}") except Exception as e: messagebox.showerror("错误", f"输入数据有误: {str(e)}") def predict_dosage_2_combined(self): """组合预测2#需矾量""" common_params = self.get_common_params() if common_params is None: return try: input_data = [ common_params[0], # 原水浊度 common_params[1], # 原水pH 0, # 1#沉淀池流量设为0,因为只预测2# float(self.flow2_combined.get()), common_params[2], # 矾原液密度 common_params[3] # 矾液浓度 ] plant_model = self.prediction_system.get_current_model() prediction = plant_model.predict_dosage_2(input_data) self.result_dosage_2_combined.config(text=f"{prediction:.4f}") except Exception as e: messagebox.showerror("错误", f"输入数据有误: {str(e)}") def predict_water_quality_combined(self): """组合预测出水浊度""" common_params = self.get_common_params() if common_params is None: return try: # 如果需矾量没有预测,使用默认值0 dosage1 = float(self.result_dosage_1_combined.cget("text")) if self.result_dosage_1_combined.cget("text") else 0 dosage2 = float(self.result_dosage_2_combined.cget("text")) if self.result_dosage_2_combined.cget("text") else 0 input_data = [ common_params[0], # 原水浊度 common_params[1], # 原水pH float(self.flow1_combined.get()), float(self.flow2_combined.get()), common_params[2], # 矾原液密度 common_params[3], # 矾液浓度 dosage1, dosage2 ] plant_model = self.prediction_system.get_current_model() prediction = plant_model.predict_water_quality(input_data) self.result_water_quality_combined.config(text=f"{prediction:.4f}") except Exception as e: messagebox.showerror("错误", f"输入数据有误: {str(e)}") def submit_feedback(self): """提交反馈""" try: actual_turb = float(self.actual_turbidity.get()) predicted_turb = float(self.predicted_turbidity_fb.cget("text")) if predicted_turb == 0: messagebox.showerror("错误", "请先进行水质预测") return common_params = self.get_common_params() if common_params is None: return input_data = [ common_params[0], # 原水浊度 common_params[1], # 原水pH float(self.flow1_wq.get()), float(self.flow2_wq.get()), common_params[2], # 矾原液密度 common_params[3], # 矾液浓度 float(self.dosage1_wq.get()), float(self.dosage2_wq.get()) ] plant_model = self.prediction_system.get_current_model() similarity = plant_model.add_feedback(input_data, actual_turb, predicted_turb) self.similarity.config(text=f"{similarity:.4f}") messagebox.showinfo("成功", "反馈已提交") except Exception as e: messagebox.showerror("错误", f"输入数据有误: {str(e)}") def retrain_model(self): """重新训练模型""" plant_model = self.prediction_system.get_current_model() plant_model.retrain_with_feedback() messagebox.showinfo("成功", f"{self.prediction_system.current_plant}水厂模型已使用反馈数据重新训练") def export_feedback(self): """导出反馈数据""" plant_model = self.prediction_system.get_current_model() success = plant_model.export_feedback_data() if success: messagebox.showinfo("成功", f"{self.prediction_system.current_plant}水厂反馈数据已成功导出") def update_curve(self): """更新关系曲线""" try: common_params = self.get_common_params() if common_params is None: return # 获取当前输入值作为基准 base_dosage_1 = float(self.dosage1_wq.get()) if self.dosage1_wq.get() else 0 base_dosage_2 = float(self.dosage2_wq.get()) if self.dosage2_wq.get() else 0 # 生成一系列需矾量值 dosage_range = np.linspace(0.5 * base_dosage_1, 1.5 * base_dosage_1, 20) # 预测对应的出水浊度 turbidity_predictions = [] for dosage in dosage_range: input_data = [ common_params[0], # 原水浊度 common_params[1], # 原水pH float(self.flow1_wq.get()), float(self.flow2_wq.get()), common_params[2], # 矾原液密度 common_params[3], # 矾液浓度 dosage, base_dosage_2 ] plant_model = self.prediction_system.get_current_model() prediction = plant_model.predict_water_quality(input_data) turbidity_predictions.append(prediction) # 绘制曲线 self.ax.clear() self.ax.plot(dosage_range, turbidity_predictions, 'b-') self.ax.set_xlabel('1#需矾量') self.ax.set_ylabel('预估出水浊度') self.ax.set_title(f'{self.prediction_system.current_plant}水厂需矾量与出水浊度关系曲线') self.ax.grid(True) # 标记当前点 if base_dosage_1 > 0: current_prediction = plant_model.predict_water_quality([ common_params[0], # 原水浊度 common_params[1], # 原水pH float(self.flow1_wq.get()), float(self.flow2_wq.get()), common_params[2], # 矾原液密度 common_params[3], # 矾液浓度 base_dosage_1, base_dosage_2 ]) self.ax.plot(base_dosage_1, current_prediction, 'ro', markersize=8) self.ax.annotate('当前点', xy=(base_dosage_1, current_prediction), xytext=(base_dosage_1*1.1, current_prediction*1.1), arrowprops=dict(facecolor='black', shrink=0.05)) self.canvas.draw() except Exception as e: messagebox.showerror("错误", f"无法生成曲线: {str(e)}") # 主程序 if __name__ == "__main__": # 创建预测系统 system = AlumDosagePredictionSystem() # 创建GUI界面 root = tk.Tk() app = AlumPredictionApp(root, system) root.mainloop()
最新发布
09-20
<think> 根据错误信息 `object has no attribute 'nametowidget'`,我们可以定位到代码中的这一行: ```python tab = self.nametowidget(tab_id) ``` 这个错误通常发生在 `self` 对象(即 `AlumPredictionApp` 实例)没有 `nametowidget` 方法。在 Tkinter 中,`nametowidget` 方法是 `Widget` 类的一个方法,用于通过组件的路径名获取组件对象。但是,`AlumPredictionApp` 类本身并不是一个 Tkinter 组件(它没有继承自任何 Tkinter 组件类),所以它没有这个方法。 然而,在 `AlumPredictionApp` 类中,`self.root` 是一个 Tkinter 窗口(`tk.Tk` 实例),而 `self.notebook` 是一个 `ttk.Notebook` 组件,它们都有 `nametowidget` 方法。 在上下文中,我们想要根据选项卡的ID(`tab_id`)获取选项卡(`ttk.Frame`)对象。我们可以通过 `self.notebook` 来调用 `nametowidget`,因为 `ttk.Notebook` 继承自 `Widget` 类。 ### 解决方案 修改 `update_plant_label` 方法中的这一行: 将 `tab = self.nametowidget(tab_id)` 改为 `tab = self.notebook.nametowidget(tab_id)` ### 修改后的代码 ```python def update_plant_label(self): """更新界面中的水厂标签""" plant_name = self.prediction_system.current_plant for tab_id in self.notebook.tabs(): # 使用 self.notebook 来调用 nametowidget tab = self.notebook.nametowidget(tab_id) if hasattr(tab, 'winfo_children'): for child in tab.winfo_children(): if isinstance(child, ttk.LabelFrame): # 注意:这里我们只更新 LabelFrame 的标题,所以我们需要确保我们只更新那些包含水厂名称的 LabelFrame。 # 获取当前标题,去掉原来的水厂名称部分,然后添加新的水厂名称。 current_text = child.cget('text') # 假设原来的标题格式是 "标签名(水厂名)",我们去掉括号及其内容 # 如果标题中没有括号,我们就直接用原来的标题加上新的水厂名称 if '(' in current_text: base_text = current_text.split('(')[0].strip() else: base_text = current_text new_text = f"{base_text}({plant_name}水厂)" child.config(text=new_text) ``` ### 解释 1. 我们使用 `self.notebook` 来调用 `nametowidget` 方法,因为 `self.notebook` 是一个 `ttk.Notebook` 组件,它具有 `nametowidget` 方法。 2. 我们修改了更新标签文本的方式,先提取原始标题中水厂名称之前的部分,然后拼接上当前水厂的名称。 3. 这样修改后,当切换水厂时,每个选项卡内的 `LabelFrame` 标题都会更新为当前水厂的名称。 ### 注意 在 `update_plant_label` 方法中,我们遍历每个选项卡,然后遍历选项卡内的每个子组件,找出 `ttk.LabelFrame` 并更新其标题。这样设计的前提是每个选项卡中只有一个 `LabelFrame`,并且我们希望更新它的标题。如果选项卡中有多个 `LabelFrame`,那么它们都会被更新。根据你的界面设计,这可能是符合预期的。 ### 修改后的完整 `update_plant_label` 方法 ```python def update_plant_label(self): """更新界面中的水厂标签""" plant_name = self.prediction_system.current_plant for tab_id in self.notebook.tabs(): tab = self.notebook.nametowidget(tab_id) if hasattr(tab, 'winfo_children'): for child in tab.winfo_children(): if isinstance(child, ttk.LabelFrame): current_text = child.cget('text') # 去除可能存在的原水厂名称 if '(' in current_text: base_text = current_text.split('(')[0].strip() else: base_text = current_text child.config(text=f"{base_text}({plant_name}水厂)") ``` ### 其他注意事项 在 `AlumPredictionApp` 的 `__init__` 方法中,我们为每个选项卡创建了 `LabelFrame`,并且初始标题都带有水厂名称(如“1#需矾量预测(JB水厂)”)。因此,当我们切换水厂时,我们希望更新这些标题中的水厂名称部分。 现在,当调用 `update_plant_label` 方法时,它会正确更新每个选项卡中 `LabelFrame` 的标题,而不会出现 `nametowidget` 的错误。 ### 测试 运行程序,切换水厂,观察每个选项卡的标题是否更新为当前水厂的名称。 如果还有其他问题,请检查是否所有选项卡都包含一个 `ttk.LabelFrame`,并且该 `LabelFrame` 的标题是我们想要更新的。 ### 完整代码修改 由于你提供了完整的代码,我在这里只修改了 `update_plant_label` 方法。请将原方法替换为上述修改后的方法。 --- §§相关问题§§: 1. Tkinter 中如何动态更新多个组件的属性? 2. 在 Tkinter 中如何处理多个窗口之间的通信? 3. 如何优化 Tkinter 应用程序的性能,特别是在频繁更新界面时? 4. 在机器学习应用中,如何设计一个实时的反馈系统来持续改进模型? </think> 根据您提供的完整代码,我发现了导致 `object has no attribute 'nametowidget'` 错误的具体原因。问题出现在 `AlumPredictionApp` 类的 `update_plant_label` 方法中: ```python def update_plant_label(self): """更新界面中的水厂标签""" plant_name = self.prediction_system.current_plant for tab_id in self.notebook.tabs(): tab = self.nametowidget(tab_id) # 这里出错 ... ``` ### 问题分析与修复方案 #### 问题原因: 1. `self.nametowidget()` 是 Tkinter `Widget` 类的方法,但 `self` (即 `AlumPredictionApp` 实例) 本身不是 Tkinter 组件 2. `self.notebook` 是 `ttk.Notebook` 组件,应该使用它的 `nametowidget()` 方法 3. 正确的调用方式是通过 `self.notebook.nametowidget(tab_id)` #### 解决方案: 修改 `update_plant_label` 方法,使用 `self.notebook` 调用 `nametowidget` ```python def update_plant_label(self): """更新界面中的水厂标签""" plant_name = self.prediction_system.current_plant for tab_id in self.notebook.tabs(): # 修改这里:使用 self.notebook.nametowidget() 而不是 self.nametowidget() tab = self.notebook.nametowidget(tab_id) if hasattr(tab, 'winfo_children'): for child in tab.winfo_children(): if isinstance(child, ttk.LabelFrame): current_text = child.cget('text') if '(' in current_text: base_text = current_text.split('(')[0].strip() else: base_text = current_text child.config(text=f"{base_text}({plant_name}水厂)") ``` ### 完整修复后的代码位置 ```python class AlumPredictionApp: def __init__(self, root, prediction_system): # ... 其他初始化代码不变 ... def update_plant_label(self): """更新界面中的水厂标签""" plant_name = self.prediction_system.current_plant for tab_id in self.notebook.tabs(): # 修复点:使用 self.notebook.nametowidget() tab = self.notebook.nametowidget(tab_id) if hasattr(tab, 'winfo_children'): for child in tab.winfo_children(): if isinstance(child, ttk.LabelFrame): current_text = child.cget('text') # 提取基础文本(去除原有水厂名称) if '(' in current_text: base_text = current_text.split('(')[0].strip() else: base_text = current_text # 更新为当前水厂名称 child.config(text=f"{base_text}({plant_name}水厂)") # ... 其他方法不变 ... ``` ### 解释说明: 1. **问题根源**: - Tkinter 的 `nametowidget()` 方法属于 `Widget` 类 - `self` (应用实例) 不是组件,而 `self.notebook` (笔记本组件) 是 - 正确调用方式应该是 `组件实例.nametowidget()` 2. **修复方案**: - 将 `self.nametowidget()` 改为 `self.notebook.nametowidget()` - 添加逻辑处理标签文本格式,确保正确更新水厂名称 3. **潜在优化**: - 可以考虑为每个选项卡单独存储基础标题,避免字符串拆分 - 添加异常处理防止无效的 tab_id ### 完整代码验证: 修复后,当切换水厂时: 1. `self.notebook.nametowidget(tab_id)` 能正确获取选项卡 2. 所有选项卡内的 `LabelFrame` 标题会更新为当前水厂名称 3. 不再出现 `AttributeError: 'AlumPredictionApp' object has no attribute 'nametowidget'` 错误 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值